@anweat/dsh-browser 0.1.17 → 0.2.0-rc.1
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 +238 -71
- package/assets/skills/dsh-browser/SKILL.md +120 -0
- package/assets/skills/dsh-browser/references/develop.md +48 -0
- package/assets/skills/dsh-browser/references/observe.md +91 -0
- package/assets/skills/dsh-browser/references/opencli.md +25 -0
- package/assets/skills/dsh-browser/references/recipes.md +149 -0
- package/assets/skills/dsh-browser/references/userscripts.md +44 -0
- package/cordis.patch.yml +4 -0
- package/lib/actions/act.d.ts +3 -0
- package/lib/actions/act.js +147 -0
- package/lib/actions/act.js.map +1 -0
- package/lib/actions/automation.d.ts +3 -0
- package/lib/actions/automation.js +356 -0
- package/lib/actions/automation.js.map +1 -0
- package/lib/actions/crawl.d.ts +3 -0
- package/lib/actions/crawl.js +28 -0
- package/lib/actions/crawl.js.map +1 -0
- package/lib/actions/errors.d.ts +53 -0
- package/lib/actions/errors.js +178 -0
- package/lib/actions/errors.js.map +1 -0
- package/lib/actions/index-view.d.ts +42 -0
- package/lib/actions/index-view.js +268 -0
- package/lib/actions/index-view.js.map +1 -0
- package/lib/actions/inspect.d.ts +3 -0
- package/lib/actions/inspect.js +35 -0
- package/lib/actions/inspect.js.map +1 -0
- package/lib/actions/observe.d.ts +3 -0
- package/lib/actions/observe.js +121 -0
- package/lib/actions/observe.js.map +1 -0
- package/lib/actions/opencli.d.ts +3 -0
- package/lib/actions/opencli.js +51 -0
- package/lib/actions/opencli.js.map +1 -0
- package/lib/actions/registry.d.ts +35 -0
- package/lib/actions/registry.js +89 -0
- package/lib/actions/registry.js.map +1 -0
- package/lib/actions/run.d.ts +34 -0
- package/lib/actions/run.js +226 -0
- package/lib/actions/run.js.map +1 -0
- package/lib/actions/runtime.d.ts +3 -0
- package/lib/actions/runtime.js +33 -0
- package/lib/actions/runtime.js.map +1 -0
- package/lib/actions/schema.d.ts +31 -0
- package/lib/actions/schema.js +309 -0
- package/lib/actions/schema.js.map +1 -0
- package/lib/actions/script.d.ts +3 -0
- package/lib/actions/script.js +97 -0
- package/lib/actions/script.js.map +1 -0
- package/lib/actions/shared.d.ts +31 -0
- package/lib/actions/shared.js +45 -0
- package/lib/actions/shared.js.map +1 -0
- package/lib/actions/surface.d.ts +22 -0
- package/lib/actions/surface.js +18 -0
- package/lib/actions/surface.js.map +1 -0
- package/lib/actions/target.d.ts +3 -0
- package/lib/actions/target.js +66 -0
- package/lib/actions/target.js.map +1 -0
- package/lib/actions/types.d.ts +181 -0
- package/lib/actions/types.js +48 -0
- package/lib/actions/types.js.map +1 -0
- package/lib/activation-rules.d.ts +29 -0
- package/lib/activation-rules.js +33 -0
- package/lib/activation-rules.js.map +1 -0
- package/lib/approval-policy.d.ts +40 -2
- package/lib/approval-policy.js +184 -97
- package/lib/approval-policy.js.map +1 -1
- package/lib/automation-assets-rpc.d.ts +8 -2
- package/lib/automation-assets-rpc.js +67 -6
- package/lib/automation-assets-rpc.js.map +1 -1
- package/lib/automation-assets.d.ts +152 -4
- package/lib/automation-assets.js +255 -15
- package/lib/automation-assets.js.map +1 -1
- package/lib/automation-convert.d.ts +23 -0
- package/lib/automation-convert.js +110 -0
- package/lib/automation-convert.js.map +1 -0
- package/lib/automation-development.d.ts +26 -0
- package/lib/automation-development.js +47 -0
- package/lib/automation-development.js.map +1 -1
- package/lib/automation-execution.d.ts +57 -1
- package/lib/automation-execution.js +167 -11
- package/lib/automation-execution.js.map +1 -1
- package/lib/automation-journal.d.ts +92 -0
- package/lib/automation-journal.js +449 -0
- package/lib/automation-journal.js.map +1 -0
- package/lib/automation-v2.d.ts +138 -0
- package/lib/automation-v2.js +631 -0
- package/lib/automation-v2.js.map +1 -0
- package/lib/automation.d.ts +82 -5
- package/lib/automation.js +239 -82
- package/lib/automation.js.map +1 -1
- package/lib/browser-service.d.ts +304 -32
- package/lib/browser-service.js +631 -182
- package/lib/browser-service.js.map +1 -1
- package/lib/client/SettingsCard.js +95 -57
- package/lib/client/SettingsCard.js.map +1 -1
- package/lib/client/asset-editor.d.ts +55 -0
- package/lib/client/asset-editor.js +101 -0
- package/lib/client/asset-editor.js.map +1 -0
- package/lib/client/automation-assets-client.d.ts +99 -2
- package/lib/client/automation-assets-client.js +243 -10
- package/lib/client/automation-assets-client.js.map +1 -1
- package/lib/client/form.d.ts +48 -4
- package/lib/client/form.js +142 -29
- package/lib/client/form.js.map +1 -1
- package/lib/client/index.d.ts +25 -2
- package/lib/client/index.js +5 -1
- package/lib/client/index.js.map +1 -1
- package/lib/client/locales.d.ts +85 -6
- package/lib/client/locales.js +64 -12
- package/lib/client/locales.js.map +1 -1
- package/lib/client/prompts-form.d.ts +67 -0
- package/lib/client/prompts-form.js +140 -0
- package/lib/client/prompts-form.js.map +1 -0
- package/lib/client/prompts-status-client.d.ts +34 -0
- package/lib/client/prompts-status-client.js +53 -0
- package/lib/client/prompts-status-client.js.map +1 -0
- package/lib/client.js +1914 -329
- package/lib/client.js.map +1 -1
- package/lib/config.d.ts +50 -1
- package/lib/config.js +31 -1
- package/lib/config.js.map +1 -1
- package/lib/dialogs.d.ts +37 -0
- package/lib/dialogs.js +73 -0
- package/lib/dialogs.js.map +1 -0
- package/lib/freedom.d.ts +23 -7
- package/lib/freedom.js +48 -59
- package/lib/freedom.js.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.js +36 -10
- package/lib/index.js.map +1 -1
- package/lib/journal.d.ts +109 -0
- package/lib/journal.js +238 -0
- package/lib/journal.js.map +1 -0
- package/lib/locator.d.ts +82 -0
- package/lib/locator.js +190 -0
- package/lib/locator.js.map +1 -0
- package/lib/observe-script.d.ts +27 -0
- package/lib/observe-script.js +565 -0
- package/lib/observe-script.js.map +1 -0
- package/lib/observe.d.ts +179 -0
- package/lib/observe.js +368 -0
- package/lib/observe.js.map +1 -0
- package/lib/policy-keys.d.ts +30 -0
- package/lib/policy-keys.js +34 -0
- package/lib/policy-keys.js.map +1 -0
- package/lib/prompt-limits.d.ts +30 -0
- package/lib/prompt-limits.js +31 -0
- package/lib/prompt-limits.js.map +1 -0
- package/lib/prompts.d.ts +131 -0
- package/lib/prompts.js +295 -0
- package/lib/prompts.js.map +1 -0
- package/lib/skill.d.ts +100 -0
- package/lib/skill.js +181 -0
- package/lib/skill.js.map +1 -0
- package/lib/tool-defs.d.ts +72 -0
- package/lib/tool-defs.js +67 -0
- package/lib/tool-defs.js.map +1 -0
- package/lib/tools.d.ts +19 -4
- package/lib/tools.js +124 -922
- package/lib/tools.js.map +1 -1
- package/package.json +5 -1
- package/scripts/dump-prompts.mjs +29 -0
- package/scripts/measure-tool-surface.mjs +190 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action dispatch: validate arguments, check availability, run the executor
|
|
3
|
+
* under a deadline, and wrap everything in the result envelope.
|
|
4
|
+
*
|
|
5
|
+
* Both tool surfaces call {@link runAction}, so the envelope and the error
|
|
6
|
+
* codes are identical whether the model reaches an action through
|
|
7
|
+
* `browser_call` or through a flat per-action tool.
|
|
8
|
+
* @module dsh-browser/actions/run
|
|
9
|
+
*/
|
|
10
|
+
import { outcomeOf } from "./types.js";
|
|
11
|
+
import { ACTIONS, findAction, traitsFor } from "./registry.js";
|
|
12
|
+
import { actionUnavailableReason } from "../freedom.js";
|
|
13
|
+
import { compactSchema, validateArgs } from "./schema.js";
|
|
14
|
+
import { targetOf } from "./shared.js";
|
|
15
|
+
import { DeadlineError, abortedByDeadline, hintFor, mapError } from "./errors.js";
|
|
16
|
+
import { effectsOf, isJournaled, isObservation, redactUrl, scrubCall, summarize } from "../journal.js";
|
|
17
|
+
/** Serialized-result cap; larger results get their longest strings shortened. */
|
|
18
|
+
export const RESULT_CHAR_LIMIT = 100_000;
|
|
19
|
+
function failure(action, executionStatus, error) {
|
|
20
|
+
return { ok: false, action, executionStatus, error };
|
|
21
|
+
}
|
|
22
|
+
/** Normalize an executor's return value into an object result. */
|
|
23
|
+
function asResult(value) {
|
|
24
|
+
// A JSON round trip drops `undefined` members, which the Host's lossless-JSON output check would reject.
|
|
25
|
+
const plain = JSON.parse(JSON.stringify(value ?? null));
|
|
26
|
+
if (plain !== null && typeof plain === 'object' && !Array.isArray(plain))
|
|
27
|
+
return plain;
|
|
28
|
+
if (Array.isArray(plain))
|
|
29
|
+
return { items: plain };
|
|
30
|
+
return { value: plain };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Shorten the longest string fields until the serialized result fits. The
|
|
34
|
+
* result stays valid JSON; the envelope reports how much text was dropped.
|
|
35
|
+
*/
|
|
36
|
+
export function truncateResult(result, limit = RESULT_CHAR_LIMIT) {
|
|
37
|
+
if (JSON.stringify(result).length <= limit)
|
|
38
|
+
return { result };
|
|
39
|
+
let omitted = 0;
|
|
40
|
+
const copy = structuredClone(result);
|
|
41
|
+
const strings = [];
|
|
42
|
+
const walk = (value) => {
|
|
43
|
+
if (Array.isArray(value))
|
|
44
|
+
value.forEach((entry, index) => { if (typeof entry === 'string')
|
|
45
|
+
strings.push({ holder: value, key: index, length: entry.length });
|
|
46
|
+
else
|
|
47
|
+
walk(entry); });
|
|
48
|
+
else if (value && typeof value === 'object') {
|
|
49
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
50
|
+
if (typeof entry === 'string')
|
|
51
|
+
strings.push({ holder: value, key, length: entry.length });
|
|
52
|
+
else
|
|
53
|
+
walk(entry);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
walk(copy);
|
|
58
|
+
strings.sort((a, b) => b.length - a.length);
|
|
59
|
+
for (const slot of strings) {
|
|
60
|
+
const size = JSON.stringify(copy).length;
|
|
61
|
+
if (size <= limit)
|
|
62
|
+
break;
|
|
63
|
+
const text = slot.holder[slot.key];
|
|
64
|
+
const excess = size - limit;
|
|
65
|
+
const keep = Math.max(200, text.length - excess - 80);
|
|
66
|
+
if (keep >= text.length)
|
|
67
|
+
continue;
|
|
68
|
+
omitted += text.length - keep;
|
|
69
|
+
slot.holder[slot.key] = text.slice(0, keep) + '…[truncated]';
|
|
70
|
+
}
|
|
71
|
+
return { result: copy, truncation: { omitted, reason: `result exceeded ${limit} characters; longest text fields were shortened` } };
|
|
72
|
+
}
|
|
73
|
+
function withDeadline(run, timeoutMs, parent, settleMs = 0) {
|
|
74
|
+
const controller = new AbortController();
|
|
75
|
+
const onAbort = () => controller.abort(parent.reason);
|
|
76
|
+
if (parent.aborted)
|
|
77
|
+
controller.abort(parent.reason);
|
|
78
|
+
else
|
|
79
|
+
parent.addEventListener('abort', onAbort, { once: true });
|
|
80
|
+
const work = run(controller.signal).then(value => ({ timedOut: false, value }));
|
|
81
|
+
// If the deadline wins, the work may still reject later; swallow it.
|
|
82
|
+
work.catch(() => { });
|
|
83
|
+
let timer;
|
|
84
|
+
let settleTimer;
|
|
85
|
+
const deadline = new Promise(resolve => {
|
|
86
|
+
timer = setTimeout(() => {
|
|
87
|
+
controller.abort(new DeadlineError('deadline'));
|
|
88
|
+
// A cooperative executor gets a bounded window to stop at its next safe point; if it returns inside the window, `work` wins the race below.
|
|
89
|
+
if (settleMs > 0)
|
|
90
|
+
settleTimer = setTimeout(() => resolve({ timedOut: true }), settleMs);
|
|
91
|
+
else
|
|
92
|
+
resolve({ timedOut: true });
|
|
93
|
+
}, timeoutMs);
|
|
94
|
+
});
|
|
95
|
+
return Promise.race([work, deadline]).finally(() => {
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
clearTimeout(settleTimer);
|
|
98
|
+
parent.removeEventListener('abort', onAbort);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/** The session's journal, when the service keeps one (test doubles of the service may not). */
|
|
102
|
+
function journalOf(ctx) {
|
|
103
|
+
try {
|
|
104
|
+
return ctx.service.journalFor?.(ctx.session);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Note the page the call is about to act on. Never fails the call. */
|
|
111
|
+
async function beginJournal(name, args, ctx) {
|
|
112
|
+
const call = { args, sensitiveControl: false };
|
|
113
|
+
try {
|
|
114
|
+
call.before = ctx.service.pageStamp?.(ctx.session);
|
|
115
|
+
// A typed value's sensitivity depends on the control (type=password...), which only the page knows, and only before the call.
|
|
116
|
+
if (name === 'act.fill' || name === 'act.type') {
|
|
117
|
+
const target = targetOf(args, false);
|
|
118
|
+
if (target !== undefined && ctx.service.inputSensitivity)
|
|
119
|
+
call.sensitiveControl = await ctx.service.inputSensitivity(target, { session: ctx.session });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch { /* the journal is evidence, not a precondition */ }
|
|
123
|
+
return call;
|
|
124
|
+
}
|
|
125
|
+
/** Record the finished call and return its seq (undefined for a call refused for its arguments: it never touched the page). Never fails the call. */
|
|
126
|
+
function finishJournal(journal, call, name, mutating, envelope, ctx) {
|
|
127
|
+
try {
|
|
128
|
+
if (envelope.error?.code === 'INVALID_ARGS')
|
|
129
|
+
return undefined;
|
|
130
|
+
const seq = journal.allocate();
|
|
131
|
+
const after = ctx.service.pageStamp?.(ctx.session);
|
|
132
|
+
const scrubbed = scrubCall(name, call.args, seq, call.sensitiveControl);
|
|
133
|
+
const outcome = { ok: envelope.ok, executionStatus: envelope.executionStatus, ...envelope.error ? { errorCode: envelope.error.code } : {} };
|
|
134
|
+
const observation = isObservation(name);
|
|
135
|
+
const targetId = name === 'target.select' ? after?.targetId ?? call.before?.targetId : call.before?.targetId ?? after?.targetId;
|
|
136
|
+
const url = after?.url ? redactUrl(after.url).url : undefined;
|
|
137
|
+
const text = envelope.result?.text;
|
|
138
|
+
journal.add({
|
|
139
|
+
seq, action: name,
|
|
140
|
+
...targetId !== undefined ? { targetId } : {},
|
|
141
|
+
...call.before?.generation !== undefined ? { generationBefore: call.before.generation } : {},
|
|
142
|
+
...after?.generation !== undefined ? { generationAfter: after.generation } : {},
|
|
143
|
+
...scrubbed.locator ? { locator: scrubbed.locator } : {},
|
|
144
|
+
params: scrubbed.params, outcome, effects: effectsOf(mutating, outcome),
|
|
145
|
+
summary: summarize(name, envelope),
|
|
146
|
+
...observation ? { observation: true } : {},
|
|
147
|
+
...url ? { url } : {},
|
|
148
|
+
...observation && envelope.ok && typeof text === 'string' ? { size: text.length } : {},
|
|
149
|
+
}, scrubbed.raw);
|
|
150
|
+
return seq;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Run one action and return the envelope. Never throws: every failure is a
|
|
158
|
+
* structured error the model can act on.
|
|
159
|
+
*/
|
|
160
|
+
export async function runAction(name, rawArgs, ctx, env) {
|
|
161
|
+
const label = typeof name === 'string' ? name : String(name);
|
|
162
|
+
const action = findAction(name);
|
|
163
|
+
if (!action) {
|
|
164
|
+
const close = typeof name === 'string' ? ACTIONS.filter(candidate => candidate.name.includes(name.split('.').pop() ?? name) || name.includes(candidate.group)).slice(0, 5).map(candidate => candidate.name) : [];
|
|
165
|
+
return failure(label, 'failed', {
|
|
166
|
+
code: 'UNKNOWN_ACTION',
|
|
167
|
+
message: `Unknown action: ${label}`,
|
|
168
|
+
hint: `Actions are named group.action. Call browser_index() to list groups${close.length ? `; similar: ${close.join(', ')}` : ''}.`,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
const unavailable = actionUnavailableReason(action, env.mode, env.options, env.enabled);
|
|
172
|
+
if (unavailable) {
|
|
173
|
+
return failure(action.name, 'failed', { code: 'POLICY_DENIED', message: `Action ${action.name} is ${unavailable}`, hint: hintFor('POLICY_DENIED') });
|
|
174
|
+
}
|
|
175
|
+
const validation = validateArgs(action.params, rawArgs);
|
|
176
|
+
if (!validation.ok) {
|
|
177
|
+
return failure(action.name, 'failed', {
|
|
178
|
+
code: 'INVALID_ARGS',
|
|
179
|
+
message: validation.errors.join('; '),
|
|
180
|
+
hint: 'Fix the arguments to match the schema below and call again.',
|
|
181
|
+
schema: compactSchema(action.name, action.params),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// The mode may allow some operations of an action and not others (automation.develop: get yes, test no).
|
|
185
|
+
const operationUnavailable = actionUnavailableReason(action, env.mode, env.options, env.enabled, validation.value);
|
|
186
|
+
if (operationUnavailable) {
|
|
187
|
+
return failure(action.name, 'failed', { code: 'POLICY_DENIED', message: `Action ${action.name} is ${operationUnavailable}`, hint: hintFor('POLICY_DENIED') });
|
|
188
|
+
}
|
|
189
|
+
const traits = traitsFor(action, validation.value);
|
|
190
|
+
if (ctx.signal.aborted)
|
|
191
|
+
return failure(action.name, 'cancelled', { code: 'CANCELLED', message: 'cancelled before start', hint: hintFor('CANCELLED') });
|
|
192
|
+
const execute = async () => {
|
|
193
|
+
let workSignal = ctx.signal;
|
|
194
|
+
try {
|
|
195
|
+
const outcome = await withDeadline(signal => { workSignal = signal; return action.execute(validation.value, { ...ctx, signal }); }, action.timeoutMs, ctx.signal, action.settleMs);
|
|
196
|
+
if (outcome.timedOut) {
|
|
197
|
+
// The work may still finish after the deadline, so a side-effecting action has an unknown outcome.
|
|
198
|
+
const status = traits.mutating ? 'outcome_unknown' : 'failed';
|
|
199
|
+
return failure(action.name, status, {
|
|
200
|
+
code: 'DEADLINE',
|
|
201
|
+
message: `${action.name} did not finish within ${action.timeoutMs} ms`,
|
|
202
|
+
hint: traits.mutating ? 'Outcome unknown: verify the page state with observe.read before retrying; do not blindly repeat a submit.' : hintFor('DEADLINE'),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// A result may carry its own outcome (a recipe that ran and failed still returns its whole report).
|
|
206
|
+
const own = outcomeOf(outcome.value);
|
|
207
|
+
const { result, truncation } = truncateResult(asResult(outcome.value));
|
|
208
|
+
return { ok: own?.ok ?? true, action: action.name, executionStatus: own?.executionStatus ?? 'completed', result, ...own?.error ? { error: own.error } : {}, ...truncation ? { truncation } : {} };
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
const body = mapError(error, action.name, { signal: workSignal });
|
|
212
|
+
// The deadline stopped work that had not returned: for a side-effecting action the outcome is unknown.
|
|
213
|
+
if (abortedByDeadline(workSignal) && traits.mutating)
|
|
214
|
+
return failure(action.name, 'outcome_unknown', { ...body, code: 'DEADLINE', hint: 'Outcome unknown: verify the page state with observe.read before retrying; do not blindly repeat a submit.' });
|
|
215
|
+
return failure(action.name, body.code === 'CANCELLED' ? 'cancelled' : 'failed', body);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const journaled = isJournaled(action.name) ? journalOf(ctx) : undefined;
|
|
219
|
+
const call = journaled ? await beginJournal(action.name, validation.value, ctx) : undefined;
|
|
220
|
+
const envelope = await execute();
|
|
221
|
+
if (!journaled || !call)
|
|
222
|
+
return envelope;
|
|
223
|
+
const seq = finishJournal(journaled, call, action.name, traits.mutating, envelope, ctx);
|
|
224
|
+
return seq === undefined ? envelope : { ...envelope, seq };
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/actions/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** `runtime` group: runtime status and the Chromium installer. @module dsh-browser/actions/runtime */
|
|
2
|
+
const cap = (text) => text.slice(0, 2000);
|
|
3
|
+
export const RUNTIME_ACTIONS = [
|
|
4
|
+
{
|
|
5
|
+
name: 'runtime.status',
|
|
6
|
+
group: 'runtime',
|
|
7
|
+
summary: 'Report runtime status: install state, automationMode, approval policies, usage buffer, this session\'s active page.',
|
|
8
|
+
notes: 'A page opened by another session is not reported.',
|
|
9
|
+
params: {},
|
|
10
|
+
approval: 'none', readOnly: true, mutating: false, concurrencySafe: true, timeoutMs: 15_000,
|
|
11
|
+
examples: [{ args: {} }],
|
|
12
|
+
async execute(_args, ctx) {
|
|
13
|
+
// Loaded here, not at the top: prompts.ts measures the catalog and so imports the registry that imports this file.
|
|
14
|
+
const { describePrompts } = await import("../prompts.js");
|
|
15
|
+
const status = await ctx.service.status({ session: ctx.session });
|
|
16
|
+
// The overrides in force (keys and lengths only) and what was ignored or is over budget, read from the live config.
|
|
17
|
+
return { ...status, prompts: describePrompts({ prompts: ctx.config.prompts, mode: ctx.config.automationMode, options: ctx.config.automationAssets, enabled: ctx.config.enabled }) };
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'runtime.install',
|
|
22
|
+
group: 'runtime',
|
|
23
|
+
summary: 'Install the bundled Playwright Chromium (large download). Run once if runtime.status reports chromium not installed.',
|
|
24
|
+
params: {},
|
|
25
|
+
approval: 'install', readOnly: false, mutating: false, concurrencySafe: false, timeoutMs: 600_000,
|
|
26
|
+
examples: [{ args: {} }],
|
|
27
|
+
async execute(_args, ctx) {
|
|
28
|
+
const result = await ctx.service.installChromium();
|
|
29
|
+
return { code: result.code, timedOut: result.timedOut, stdout: cap(result.stdout ?? ''), stderr: cap(result.stderr ?? '') };
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/actions/runtime.ts"],"names":[],"mappings":"AAAA,sGAAsG;AAItG,MAAM,GAAG,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;AAEzD,MAAM,CAAC,MAAM,eAAe,GAAgB;IAC1C;QACE,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,qHAAqH;QAC9H,KAAK,EAAE,mDAAmD;QAC1D,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM;QAC3F,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACxB,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;YACtB,mHAAmH;YACnH,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;YACzD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YACjE,oHAAoH;YACpH,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,gBAAgB,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAA;QACrL,CAAC;KACF;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,sHAAsH;QAC/H,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO;QACjG,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACxB,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;YACtB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,CAAA;YAClD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAA;QAC7H,CAAC;KACF;CACF,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared sub-schemas plus the validator and renderers for action parameters.
|
|
3
|
+
*
|
|
4
|
+
* `LOCATOR_SCHEMA` and friends are defined exactly once. Actions reference them
|
|
5
|
+
* with `{ ref: 'locator' }`; the flat tool surface expands the reference inline
|
|
6
|
+
* (the Host needs a self-contained schema per tool) and the indexed surface
|
|
7
|
+
* prints them once in the L2 detail.
|
|
8
|
+
* @module dsh-browser/actions/schema
|
|
9
|
+
*/
|
|
10
|
+
import type { ParamNode, ParamSchema, SharedSchemaName } from './types.ts';
|
|
11
|
+
export declare const SHARED_SCHEMAS: Record<SharedSchemaName, ParamNode>;
|
|
12
|
+
/** The two params every element-targeting action accepts. */
|
|
13
|
+
export declare const TARGET_PARAMS: ParamSchema;
|
|
14
|
+
/** Optional guard of the act.* actions that change or press into the page. */
|
|
15
|
+
export declare const EXPECT_PARAMS: ParamSchema;
|
|
16
|
+
/** Expand every `ref` inline: the self-contained shape a flat tool needs. */
|
|
17
|
+
export declare function expandNode(node: ParamNode): ParamNode;
|
|
18
|
+
export declare function expandParams(params: ParamSchema): ParamSchema;
|
|
19
|
+
export interface ValidationResult {
|
|
20
|
+
ok: boolean;
|
|
21
|
+
value: Record<string, unknown>;
|
|
22
|
+
errors: string[];
|
|
23
|
+
}
|
|
24
|
+
/** Validate call arguments against an action's parameter schema. */
|
|
25
|
+
export declare function validateArgs(params: ParamSchema, args: unknown): ValidationResult;
|
|
26
|
+
/** One-line parameter summary: `selector?: string, locator?: $locator`. */
|
|
27
|
+
export declare function compactParams(params: ParamSchema): string;
|
|
28
|
+
/** Compact schema block attached to INVALID_ARGS replies. */
|
|
29
|
+
export declare function compactSchema(action: string, params: ParamSchema): string;
|
|
30
|
+
/** Full parameter listing with descriptions, followed by each shared sub-schema once. */
|
|
31
|
+
export declare function describeParams(params: ParamSchema): string[];
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared sub-schemas plus the validator and renderers for action parameters.
|
|
3
|
+
*
|
|
4
|
+
* `LOCATOR_SCHEMA` and friends are defined exactly once. Actions reference them
|
|
5
|
+
* with `{ ref: 'locator' }`; the flat tool surface expands the reference inline
|
|
6
|
+
* (the Host needs a self-contained schema per tool) and the indexed surface
|
|
7
|
+
* prints them once in the L2 detail.
|
|
8
|
+
* @module dsh-browser/actions/schema
|
|
9
|
+
*/
|
|
10
|
+
const FRAME_SCHEMA = {
|
|
11
|
+
type: 'object',
|
|
12
|
+
additionalProperties: false,
|
|
13
|
+
description: 'Iframe to search inside. Use exactly one field.',
|
|
14
|
+
properties: {
|
|
15
|
+
selector: { type: 'string', description: 'CSS selector for an iframe.' },
|
|
16
|
+
name: { type: 'string', description: 'Frame name.' },
|
|
17
|
+
url: { type: 'string', description: 'Playwright frame URL/glob.' },
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const LOCATOR_SCHEMA = {
|
|
21
|
+
type: 'object',
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
description: 'Element locator, strict: it must match exactly one element, else LOCATOR_AMBIGUOUS lists candidates. Use exactly one of selector, role, text, label, or testId.',
|
|
24
|
+
properties: {
|
|
25
|
+
selector: { type: 'string', description: 'CSS selector.' },
|
|
26
|
+
role: { type: 'string', description: 'Accessible role used by Playwright getByRole.' },
|
|
27
|
+
name: { type: 'string', description: 'Optional accessible name; valid only with role.' },
|
|
28
|
+
text: { type: 'string', description: 'Visible text used by Playwright getByText.' },
|
|
29
|
+
label: { type: 'string', description: 'Form label used by Playwright getByLabel.' },
|
|
30
|
+
exact: { type: 'boolean', description: 'Require an exact semantic match. Defaults to false.' },
|
|
31
|
+
testId: { type: 'string', description: 'data-testid value.' },
|
|
32
|
+
framePath: { type: 'array', items: { type: 'string' }, description: 'Nested iframes, outermost first, each a CSS selector. Alternative to frame.' },
|
|
33
|
+
index: { type: 'number', description: 'Pick the n-th match (0-based) of an ambiguous locator. Requires indexReason.' },
|
|
34
|
+
indexReason: { type: 'string', description: 'Why that match and not the others. Required with index.' },
|
|
35
|
+
frame: { ref: 'frame' },
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
const RECIPE_LOCATOR_SCHEMA = {
|
|
39
|
+
type: 'object',
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
description: 'v2, strict: one match or LOCATOR_AMBIGUOUS. One of role (+name, exact), label, text, testId, css.',
|
|
42
|
+
properties: {
|
|
43
|
+
role: { type: 'string' },
|
|
44
|
+
name: { type: 'string', description: 'with role' },
|
|
45
|
+
exact: { type: 'boolean' },
|
|
46
|
+
label: { type: 'string' },
|
|
47
|
+
text: { type: 'string' },
|
|
48
|
+
testId: { type: 'string' },
|
|
49
|
+
css: { type: 'string' },
|
|
50
|
+
framePath: { type: 'array', items: { type: 'string' }, description: 'iframe selectors, outermost first' },
|
|
51
|
+
index: { type: 'number', description: '0-based; needs indexReason' },
|
|
52
|
+
indexReason: { type: 'string' },
|
|
53
|
+
explicitFirst: { type: 'boolean', description: 'v1 converter marker' },
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
const RECIPE_STEP_SCHEMA = {
|
|
57
|
+
type: 'object',
|
|
58
|
+
additionalProperties: false,
|
|
59
|
+
description: 'v1: selector (first match). v2: locator (strict).',
|
|
60
|
+
properties: {
|
|
61
|
+
type: { type: 'string', required: true, enum: ['wait', 'click', 'fill', 'clear', 'type', 'press', 'select', 'check', 'hover', 'scroll', 'goto', 'extract', 'assert', 'screenshot'] },
|
|
62
|
+
condition: { type: 'string', enum: ['selector', 'locator', 'text', 'url', 'load', 'time'], description: 'wait kind' },
|
|
63
|
+
selector: { type: 'string', description: 'v1 CSS' },
|
|
64
|
+
locator: { ref: 'recipeLocator' },
|
|
65
|
+
value: { type: 'string', description: 'fill/type/select; wait text/url' },
|
|
66
|
+
allowEmpty: { type: 'boolean', description: 'v2 fill ""' },
|
|
67
|
+
text: { type: 'string', description: 'assert' },
|
|
68
|
+
urlIncludes: { type: 'string', description: 'v2 assert' },
|
|
69
|
+
url: { type: 'string', description: 'v2 goto, inside domains' },
|
|
70
|
+
key: { type: 'string' },
|
|
71
|
+
timeoutMs: { type: 'number', description: '1-30000; v2 extract/assert 5000' },
|
|
72
|
+
waitMs: { type: 'number' },
|
|
73
|
+
deltaY: { type: 'number' },
|
|
74
|
+
checked: { type: 'boolean' },
|
|
75
|
+
mode: { type: 'string', enum: ['text', 'html', 'links', 'attribute'] },
|
|
76
|
+
attribute: { type: 'string' },
|
|
77
|
+
limit: { type: 'number' },
|
|
78
|
+
as: { type: 'string', description: 'v2 extract output name' },
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
const POSTCONDITION_SCHEMA = {
|
|
82
|
+
type: 'object',
|
|
83
|
+
additionalProperties: false,
|
|
84
|
+
description: 'One of selector, text, urlIncludes, output (+ nonEmpty or allowEmpty true).',
|
|
85
|
+
properties: {
|
|
86
|
+
selector: { type: 'string', description: 'visible CSS' },
|
|
87
|
+
text: { type: 'string', description: 'visible text' },
|
|
88
|
+
urlIncludes: { type: 'string' },
|
|
89
|
+
output: { type: 'string', description: 'an extract as name' },
|
|
90
|
+
nonEmpty: { type: 'boolean' },
|
|
91
|
+
allowEmpty: { type: 'boolean' },
|
|
92
|
+
timeoutMs: { type: 'number', description: 'default 5000' },
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
const INPUT_SPEC_SCHEMA = {
|
|
96
|
+
type: 'object',
|
|
97
|
+
additionalProperties: false,
|
|
98
|
+
description: 'Typed input, checked and converted before running.',
|
|
99
|
+
properties: {
|
|
100
|
+
name: { type: 'string', required: true, description: 'placeholder name (double curly braces in steps)' },
|
|
101
|
+
type: { type: 'string', required: true, enum: ['string', 'number', 'enum'] },
|
|
102
|
+
required: { type: 'boolean', description: 'default true' },
|
|
103
|
+
example: { type: 'string', description: 'sample, as text' },
|
|
104
|
+
enumValues: { type: 'array', items: { type: 'string' }, description: 'for enum' },
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
const OUTPUT_SPEC_SCHEMA = {
|
|
108
|
+
type: 'object',
|
|
109
|
+
additionalProperties: false,
|
|
110
|
+
description: 'Named output of the extract step with the same as.',
|
|
111
|
+
properties: {
|
|
112
|
+
name: { type: 'string', required: true },
|
|
113
|
+
type: { type: 'string', required: true, enum: ['string', 'number', 'json'] },
|
|
114
|
+
dedupe: { type: 'boolean', description: 'drop repeated lines/elements' },
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
export const SHARED_SCHEMAS = {
|
|
118
|
+
frame: FRAME_SCHEMA,
|
|
119
|
+
locator: LOCATOR_SCHEMA,
|
|
120
|
+
recipeStep: RECIPE_STEP_SCHEMA,
|
|
121
|
+
recipeLocator: RECIPE_LOCATOR_SCHEMA,
|
|
122
|
+
postcondition: POSTCONDITION_SCHEMA,
|
|
123
|
+
inputSpec: INPUT_SPEC_SCHEMA,
|
|
124
|
+
outputSpec: OUTPUT_SPEC_SCHEMA,
|
|
125
|
+
};
|
|
126
|
+
/** The two params every element-targeting action accepts. */
|
|
127
|
+
export const TARGET_PARAMS = {
|
|
128
|
+
selector: { type: 'string', description: 'CSS selector. Omit when locator is given; pass exactly one of selector or locator.' },
|
|
129
|
+
locator: { ref: 'locator' },
|
|
130
|
+
};
|
|
131
|
+
/** Optional guard of the act.* actions that change or press into the page. */
|
|
132
|
+
export const EXPECT_PARAMS = {
|
|
133
|
+
expectGeneration: { type: 'number', description: 'generation from the last observe.read/act result; if the page navigated since, fails TARGET_STALE and does nothing.' },
|
|
134
|
+
};
|
|
135
|
+
function resolve(node) {
|
|
136
|
+
if (!node.ref)
|
|
137
|
+
return node;
|
|
138
|
+
const shared = SHARED_SCHEMAS[node.ref];
|
|
139
|
+
return { ...shared, ...node.description ? { description: node.description } : {} };
|
|
140
|
+
}
|
|
141
|
+
/** Expand every `ref` inline: the self-contained shape a flat tool needs. */
|
|
142
|
+
export function expandNode(node) {
|
|
143
|
+
const resolved = resolve(node);
|
|
144
|
+
const { ref: _ref, ...rest } = resolved;
|
|
145
|
+
const out = { ...rest };
|
|
146
|
+
if (resolved.items)
|
|
147
|
+
out.items = expandNode(resolved.items);
|
|
148
|
+
if (resolved.properties)
|
|
149
|
+
out.properties = Object.fromEntries(Object.entries(resolved.properties).map(([key, value]) => [key, expandNode(value)]));
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
export function expandParams(params) {
|
|
153
|
+
return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, expandNode(value)]));
|
|
154
|
+
}
|
|
155
|
+
const MAX_ERRORS = 6;
|
|
156
|
+
function isRecord(value) {
|
|
157
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
158
|
+
}
|
|
159
|
+
function describeType(value) {
|
|
160
|
+
if (Array.isArray(value))
|
|
161
|
+
return 'array';
|
|
162
|
+
if (value === null)
|
|
163
|
+
return 'null';
|
|
164
|
+
return typeof value;
|
|
165
|
+
}
|
|
166
|
+
function validateObject(properties, open, value, path, errors) {
|
|
167
|
+
if (!isRecord(value)) {
|
|
168
|
+
errors.push(`${path || 'args'}: expected object, got ${describeType(value)}`);
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
const out = {};
|
|
172
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
173
|
+
const node = properties[key];
|
|
174
|
+
if (!node) {
|
|
175
|
+
if (open)
|
|
176
|
+
out[key] = entry;
|
|
177
|
+
else
|
|
178
|
+
errors.push(`${path ? path + '.' : ''}${key}: unknown argument (allowed: ${Object.keys(properties).join(', ') || 'none'})`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
// Models often send null for an omitted optional value; treat it as absent.
|
|
182
|
+
if (entry === null || entry === undefined)
|
|
183
|
+
continue;
|
|
184
|
+
const checked = validateNode(node, entry, `${path ? path + '.' : ''}${key}`, errors);
|
|
185
|
+
if (checked !== undefined)
|
|
186
|
+
out[key] = checked;
|
|
187
|
+
}
|
|
188
|
+
for (const [key, node] of Object.entries(properties)) {
|
|
189
|
+
if (node.required && !(key in out) && !errors.some(error => error.startsWith(`${path ? path + '.' : ''}${key}:`))) {
|
|
190
|
+
errors.push(`${path ? path + '.' : ''}${key}: required`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
function validateNode(raw, value, path, errors) {
|
|
196
|
+
if (errors.length >= MAX_ERRORS)
|
|
197
|
+
return undefined;
|
|
198
|
+
const node = resolve(raw);
|
|
199
|
+
switch (node.type) {
|
|
200
|
+
case 'string':
|
|
201
|
+
if (typeof value !== 'string') {
|
|
202
|
+
errors.push(`${path}: expected string, got ${describeType(value)}`);
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
if (node.enum && !node.enum.includes(value)) {
|
|
206
|
+
errors.push(`${path}: must be one of ${node.enum.join(' | ')}`);
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
return value;
|
|
210
|
+
case 'number':
|
|
211
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
212
|
+
errors.push(`${path}: expected number, got ${describeType(value)}`);
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
return value;
|
|
216
|
+
case 'boolean':
|
|
217
|
+
if (typeof value !== 'boolean') {
|
|
218
|
+
errors.push(`${path}: expected boolean, got ${describeType(value)}`);
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
return value;
|
|
222
|
+
case 'array': {
|
|
223
|
+
if (!Array.isArray(value)) {
|
|
224
|
+
errors.push(`${path}: expected array, got ${describeType(value)}`);
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
if (!node.items)
|
|
228
|
+
return value;
|
|
229
|
+
const items = [];
|
|
230
|
+
value.forEach((entry, index) => {
|
|
231
|
+
const checked = validateNode(node.items, entry, `${path}[${index}]`, errors);
|
|
232
|
+
if (checked !== undefined)
|
|
233
|
+
items.push(checked);
|
|
234
|
+
});
|
|
235
|
+
return items;
|
|
236
|
+
}
|
|
237
|
+
case 'object':
|
|
238
|
+
return validateObject(node.properties ?? {}, node.additionalProperties === true || !node.properties, value, path, errors);
|
|
239
|
+
default:
|
|
240
|
+
return value;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** Validate call arguments against an action's parameter schema. */
|
|
244
|
+
export function validateArgs(params, args) {
|
|
245
|
+
const errors = [];
|
|
246
|
+
const input = args === undefined || args === null ? {} : args;
|
|
247
|
+
const value = validateObject(params, false, input, '', errors) ?? {};
|
|
248
|
+
return { ok: errors.length === 0, value, errors };
|
|
249
|
+
}
|
|
250
|
+
// --- rendering ------------------------------------------------------------
|
|
251
|
+
function refsOf(node, into) {
|
|
252
|
+
if (node.ref) {
|
|
253
|
+
into.add(node.ref);
|
|
254
|
+
refsOf(SHARED_SCHEMAS[node.ref], into);
|
|
255
|
+
}
|
|
256
|
+
if (node.items)
|
|
257
|
+
refsOf(node.items, into);
|
|
258
|
+
for (const child of Object.values(node.properties ?? {}))
|
|
259
|
+
refsOf(child, into);
|
|
260
|
+
}
|
|
261
|
+
function usedRefs(params) {
|
|
262
|
+
const refs = new Set();
|
|
263
|
+
for (const node of Object.values(params))
|
|
264
|
+
refsOf(node, refs);
|
|
265
|
+
return [...refs];
|
|
266
|
+
}
|
|
267
|
+
function compactNode(node) {
|
|
268
|
+
if (node.ref)
|
|
269
|
+
return '$' + node.ref;
|
|
270
|
+
switch (node.type) {
|
|
271
|
+
case 'string': return node.enum ? node.enum.map(value => JSON.stringify(value)).join('|') : 'string';
|
|
272
|
+
case 'number': return 'number';
|
|
273
|
+
case 'boolean': return 'boolean';
|
|
274
|
+
case 'array': return (node.items ? compactNode(node.items) : 'any') + '[]';
|
|
275
|
+
case 'object': return node.properties ? '{' + compactFields(node.properties) + '}' : 'object';
|
|
276
|
+
default: return 'any';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function compactFields(properties) {
|
|
280
|
+
return Object.entries(properties).map(([key, node]) => `${key}${node.required ? '' : '?'}: ${compactNode(node)}`).join(', ');
|
|
281
|
+
}
|
|
282
|
+
/** One-line parameter summary: `selector?: string, locator?: $locator`. */
|
|
283
|
+
export function compactParams(params) {
|
|
284
|
+
return compactFields(params);
|
|
285
|
+
}
|
|
286
|
+
/** Compact schema block attached to INVALID_ARGS replies. */
|
|
287
|
+
export function compactSchema(action, params) {
|
|
288
|
+
const lines = [`${action}(${compactFields(params)})`];
|
|
289
|
+
for (const ref of usedRefs(params))
|
|
290
|
+
lines.push(`$${ref} = {${compactFields(SHARED_SCHEMAS[ref].properties ?? {})}}`);
|
|
291
|
+
return lines.join('\n');
|
|
292
|
+
}
|
|
293
|
+
function describedFields(properties, indent) {
|
|
294
|
+
return Object.entries(properties).map(([key, node]) => {
|
|
295
|
+
const note = node.description ? ' - ' + node.description : '';
|
|
296
|
+
return `${indent}${key}${node.required ? '' : '?'}: ${compactNode(node)}${note}`;
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
/** Full parameter listing with descriptions, followed by each shared sub-schema once. */
|
|
300
|
+
export function describeParams(params) {
|
|
301
|
+
const lines = Object.keys(params).length ? describedFields(params, ' ') : [' (no arguments)'];
|
|
302
|
+
for (const ref of usedRefs(params)) {
|
|
303
|
+
const shared = SHARED_SCHEMAS[ref];
|
|
304
|
+
lines.push(`$${ref}${shared.description ? ' - ' + shared.description : ''}`);
|
|
305
|
+
lines.push(...describedFields(shared.properties ?? {}, ' '));
|
|
306
|
+
}
|
|
307
|
+
return lines;
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=schema.js.map
|