mindoodb-app-sdk 0.0.70 → 0.0.72

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.
@@ -66,6 +66,296 @@ function assertValidMindooDBCreateIds(input, methodName = "createDocument") {
66
66
  }
67
67
  }
68
68
 
69
+ // src/inspection.ts
70
+ var MINDOODB_INSPECT_DOCUMENT = "mindoo.inspect.document@1";
71
+ var MINDOODB_INSPECT_SPREADSHEET = "mindoo.inspect.spreadsheet@1";
72
+ var MINDOODB_INSPECT_SLIDES = "mindoo.inspect.slides@1";
73
+ var MINDOODB_APP_INSPECTION_FIELD = "inspection";
74
+ var MINDOODB_APP_INSPECTION_SUMMARY_MAX_BYTES = 8 * 1024;
75
+ var MINDOODB_APP_INSPECTION_MAX_BYTES = 256 * 1024;
76
+ var MINDOODB_APP_ISSUES_MAX = 100;
77
+ var MindooDBAppEmbedValidationError = class extends Error {
78
+ constructor(issues) {
79
+ const first = issues.find((issue) => issue.severity === "error") ?? issues[0];
80
+ super(first ? first.message : "The document was not saved.");
81
+ this.issues = issues;
82
+ this.name = "MindooDBAppEmbedValidationError";
83
+ }
84
+ issues;
85
+ };
86
+ var SUPPORTS_CAPABILITY = /^[a-z][a-z0-9-]{0,31}$/;
87
+ function mindooDBAppComponentSupports(supports, requirement) {
88
+ const wanted = requirement.trim();
89
+ return (supports ?? []).some((entry) => entry === wanted || !wanted.includes(":") && entry.startsWith(`${wanted}:`));
90
+ }
91
+ function mindooDBAppInspectContracts(supports) {
92
+ return (supports ?? []).filter((entry) => entry.startsWith("inspect:")).map((entry) => entry.slice("inspect:".length));
93
+ }
94
+ function isPlainObject(value) {
95
+ return typeof value === "object" && value !== null && !Array.isArray(value);
96
+ }
97
+ function normalizeMindooDBAppInspectAnchor(raw) {
98
+ if (!isPlainObject(raw)) {
99
+ return void 0;
100
+ }
101
+ if (raw.kind === "heading" && typeof raw.id === "string" && raw.id && raw.id.length <= 200) {
102
+ return { kind: "heading", id: raw.id };
103
+ }
104
+ if (raw.kind === "cell" && typeof raw.ref === "string" && raw.ref && raw.ref.length <= 200) {
105
+ return { kind: "cell", ref: raw.ref };
106
+ }
107
+ if (raw.kind === "slide" && Number.isInteger(raw.index) && raw.index >= 0) {
108
+ return { kind: "slide", index: raw.index };
109
+ }
110
+ return void 0;
111
+ }
112
+ function normalizeMindooDBAppIssues(raw) {
113
+ if (!Array.isArray(raw)) {
114
+ return [];
115
+ }
116
+ const issues = [];
117
+ for (const entry of raw) {
118
+ if (issues.length >= MINDOODB_APP_ISSUES_MAX) {
119
+ break;
120
+ }
121
+ if (!isPlainObject(entry) || typeof entry.message !== "string" || !entry.message.trim()) {
122
+ continue;
123
+ }
124
+ const severity = entry.severity === "warning" || entry.severity === "info" ? entry.severity : entry.severity === "error" ? "error" : null;
125
+ if (!severity) {
126
+ continue;
127
+ }
128
+ const anchor = normalizeMindooDBAppInspectAnchor(entry.anchor);
129
+ const code = typeof entry.code === "string" && entry.code.trim() ? entry.code.trim().slice(0, 64) : void 0;
130
+ issues.push({
131
+ severity,
132
+ message: entry.message.trim().slice(0, 500),
133
+ ...anchor ? { anchor } : {},
134
+ ...code ? { code } : {}
135
+ });
136
+ }
137
+ return issues;
138
+ }
139
+ function normalizeMindooDBAppInspectRequest(raw) {
140
+ const input = isPlainObject(raw) ? raw : {};
141
+ const strings = (value, max) => Array.isArray(value) ? [...new Set(value.filter((entry) => typeof entry === "string" && !!entry && entry.length <= 200))].slice(0, max) : [];
142
+ const include = strings(input.include, 16);
143
+ const cells = strings(input.cells, 200);
144
+ const maxTextLength = Number(input.maxTextLength);
145
+ return {
146
+ ...typeof input.contract === "string" && input.contract ? { contract: input.contract.slice(0, 200) } : {},
147
+ ...include.length ? { include } : {},
148
+ ...cells.length ? { cells } : {},
149
+ ...Number.isFinite(maxTextLength) && maxTextLength > 0 ? { maxTextLength: Math.min(Math.floor(maxTextLength), 5e4) } : {}
150
+ };
151
+ }
152
+ function normalizeMindooDBAppInspection(raw) {
153
+ let json;
154
+ try {
155
+ json = JSON.stringify(raw);
156
+ } catch {
157
+ throw new Error("An inspection must be plain JSON.");
158
+ }
159
+ if (!json || json.length > MINDOODB_APP_INSPECTION_MAX_BYTES) {
160
+ throw new Error(`An inspection must not be larger than ${MINDOODB_APP_INSPECTION_MAX_BYTES / 1024} KiB.`);
161
+ }
162
+ const value = JSON.parse(json);
163
+ if (!isPlainObject(value) || typeof value.contract !== "string" || !value.contract) {
164
+ throw new Error("An inspection must be an object with a contract.");
165
+ }
166
+ return value;
167
+ }
168
+ var SUMMARY_TEXT_STEPS = [500, 200, 0];
169
+ var SUMMARY_LIST_STEPS = [50, 20, 5, 0];
170
+ function shorten(value, textMax, listMax, marks) {
171
+ if (typeof value === "string") {
172
+ if (value.length <= textMax) return value;
173
+ marks.truncated = true;
174
+ return value.slice(0, textMax);
175
+ }
176
+ if (Array.isArray(value)) {
177
+ if (value.length > listMax) marks.truncated = true;
178
+ return value.slice(0, listMax).map((entry) => shorten(entry, Math.min(textMax || 80, 80), listMax, marks));
179
+ }
180
+ if (isPlainObject(value)) {
181
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, shorten(entry, textMax, listMax, marks)]));
182
+ }
183
+ return value;
184
+ }
185
+ function summarizeMindooDBAppInspection(inspection, maxBytes = MINDOODB_APP_INSPECTION_SUMMARY_MAX_BYTES) {
186
+ const { cells: _cells, ...rest } = inspection;
187
+ const base = JSON.parse(JSON.stringify(rest));
188
+ for (const textMax of SUMMARY_TEXT_STEPS) {
189
+ for (const listMax of SUMMARY_LIST_STEPS) {
190
+ const marks = { truncated: false };
191
+ const next = shorten(base, textMax, listMax, marks);
192
+ if (textMax === 0 && typeof next.text === "string") delete next.text;
193
+ next.contract = inspection.contract;
194
+ if (typeof inspection.subject === "string") next.subject = inspection.subject.slice(0, 200);
195
+ if (marks.truncated || inspection.truncated) next.truncated = true;
196
+ if (JSON.stringify(next).length <= maxBytes) {
197
+ return next;
198
+ }
199
+ }
200
+ }
201
+ return { contract: inspection.contract, truncated: true };
202
+ }
203
+ function mindooDBAppInspectionSummaryValue(inspection) {
204
+ return MindooDBAppValue.atomic(JSON.stringify(summarizeMindooDBAppInspection(inspection)));
205
+ }
206
+ function readMindooDBAppInspectionSummary(root) {
207
+ let value = root?.[MINDOODB_APP_INSPECTION_FIELD];
208
+ if (typeof value === "string") {
209
+ try {
210
+ value = JSON.parse(value);
211
+ } catch {
212
+ return null;
213
+ }
214
+ }
215
+ return isPlainObject(value) && typeof value.contract === "string" ? value : null;
216
+ }
217
+ function outcomeIssues(rule, outcome) {
218
+ if (!outcome) return [];
219
+ if (typeof outcome === "string") {
220
+ return [{ severity: rule.severity ?? "error", message: outcome, code: rule.code }];
221
+ }
222
+ return (Array.isArray(outcome) ? outcome : [outcome]).map((issue) => ({ code: rule.code, ...issue }));
223
+ }
224
+ function defineDocumentRules(definition) {
225
+ const request = normalizeMindooDBAppInspectRequest(definition);
226
+ function check(inspection) {
227
+ if (!inspection || definition.contract && inspection.contract !== definition.contract) {
228
+ return [];
229
+ }
230
+ const issues = definition.rules.flatMap((rule) => {
231
+ try {
232
+ return outcomeIssues(rule, rule.check(inspection));
233
+ } catch (error) {
234
+ return [
235
+ {
236
+ severity: "warning",
237
+ code: rule.code,
238
+ message: `Check "${rule.code}" failed: ${error instanceof Error ? error.message : String(error)}`
239
+ }
240
+ ];
241
+ }
242
+ });
243
+ return normalizeMindooDBAppIssues(issues);
244
+ }
245
+ const rules = {
246
+ request,
247
+ check,
248
+ checkRoot: (root) => check(readMindooDBAppInspectionSummary(root)),
249
+ beforeSave: ({ inspection }) => ({ issues: check(inspection) }),
250
+ attach: (embed) => embed.onBeforeSave(rules.beforeSave, { inspect: request })
251
+ };
252
+ return rules;
253
+ }
254
+ function plural(count, one, many) {
255
+ return `${count} ${count === 1 ? one : many}`;
256
+ }
257
+ var mindooDBAppInspectRules = {
258
+ /** Documents: no placeholder or MERGEFIELD left open. */
259
+ noOpenPlaceholders(severity = "error", message) {
260
+ return {
261
+ code: "open-placeholders",
262
+ severity,
263
+ check: (inspection) => {
264
+ const names = (inspection.placeholders ?? []).map((entry) => entry.name);
265
+ if (!names.length) return null;
266
+ return message?.(names) ?? `${plural(names.length, "placeholder is", "placeholders are")} not filled in: ${names.slice(0, 5).join(", ")}${names.length > 5 ? ", \u2026" : ""}`;
267
+ }
268
+ };
269
+ },
270
+ /** Documents: every comment resolved. */
271
+ noOpenComments(severity = "warning", message) {
272
+ return {
273
+ code: "open-comments",
274
+ severity,
275
+ check: (inspection) => inspection.openComments > 0 ? message?.(inspection.openComments) ?? `${plural(inspection.openComments, "comment is", "comments are")} not resolved.` : null
276
+ };
277
+ },
278
+ /** Documents: every tracked change accepted or rejected. */
279
+ noOpenTrackedChanges(severity = "warning", message) {
280
+ return {
281
+ code: "open-tracked-changes",
282
+ severity,
283
+ check: (inspection) => inspection.openTrackedChanges > 0 ? message?.(inspection.openTrackedChanges) ?? `${plural(inspection.openTrackedChanges, "tracked change is", "tracked changes are")} not accepted or rejected.` : null
284
+ };
285
+ },
286
+ /** Spreadsheets: no formula evaluates to an error; one issue per cell. */
287
+ noFormulaErrors(severity = "error") {
288
+ return {
289
+ code: "formula-errors",
290
+ severity,
291
+ check: (inspection) => (inspection.formulaErrors ?? []).map((entry) => ({
292
+ severity,
293
+ message: `${entry.ref}: ${entry.error}`,
294
+ anchor: { kind: "cell", ref: entry.ref }
295
+ }))
296
+ };
297
+ },
298
+ /** Presentations: no layout placeholder left empty; one issue per slide. */
299
+ noEmptySlidePlaceholders(severity = "warning") {
300
+ return {
301
+ code: "empty-placeholders",
302
+ severity,
303
+ check: (inspection) => {
304
+ const bySlide = /* @__PURE__ */ new Map();
305
+ for (const entry of inspection.emptyPlaceholders ?? []) {
306
+ bySlide.set(entry.slide, [...bySlide.get(entry.slide) ?? [], entry.placeholder]);
307
+ }
308
+ return [...bySlide.entries()].map(([slide, names]) => ({
309
+ severity,
310
+ message: `Slide ${slide + 1}: empty ${names.join(", ")}`,
311
+ anchor: { kind: "slide", index: slide }
312
+ }));
313
+ }
314
+ };
315
+ }
316
+ };
317
+ function isMindooDBAppSupportsEntry(entry, contractPattern) {
318
+ const [capability, contract, ...rest] = entry.split(":");
319
+ if (rest.length || !capability || !SUPPORTS_CAPABILITY.test(capability)) {
320
+ return false;
321
+ }
322
+ return contract === void 0 || contractPattern.test(contract);
323
+ }
324
+ async function performMindooDBAppEmbeddingSave(steps) {
325
+ const validation = await steps.validate();
326
+ if (!validation.ok) {
327
+ if (validation.issues.length && steps.showIssues) {
328
+ try {
329
+ await steps.showIssues(validation.issues);
330
+ } catch (error) {
331
+ console.warn("[mindoodb-app-sdk] Showing issues failed.", error);
332
+ }
333
+ }
334
+ throw new MindooDBAppEmbedValidationError(validation.issues);
335
+ }
336
+ let inspection = null;
337
+ if (steps.provider) {
338
+ try {
339
+ inspection = mindooDBAppInspectionSummaryValue(normalizeMindooDBAppInspection(await steps.provider({})));
340
+ } catch (error) {
341
+ console.warn("[mindoodb-app-sdk] Could not summarize the document.", error);
342
+ }
343
+ }
344
+ await steps.flush({ inspection, issues: validation.issues });
345
+ await steps.saved();
346
+ return validation;
347
+ }
348
+ async function resolveMindooDBAppEmbedValidation(issues, interactive, confirm) {
349
+ if (issues.some((issue) => issue.severity === "error")) {
350
+ return { ok: false, issues };
351
+ }
352
+ const warnings = issues.filter((issue) => issue.severity === "warning");
353
+ if (!warnings.length || !interactive) {
354
+ return { ok: true, issues };
355
+ }
356
+ return { ok: await confirm(warnings) === true, issues };
357
+ }
358
+
69
359
  // src/appDefinition.ts
70
360
  var MINDOODB_APP_DEFINITION_FORMAT = "mindoodb.haven.app";
71
361
  var MINDOODB_APP_DEFINITION_VERSION = 1;
@@ -86,8 +376,17 @@ var MINDOODB_APP_DEFINITION_REGISTRATION_PERMISSIONS = ["proposeapps"];
86
376
  var MINDOODB_APP_LISTING_SUMMARY_MAX = 300;
87
377
  var MINDOODB_APP_LISTING_DESCRIPTION_MAX = 4e3;
88
378
  var MINDOODB_APP_LISTING_MAX_SCREENSHOTS = 8;
379
+ var MINDOODB_APP_AGENT_SUMMARY_MAX = 400;
380
+ var MINDOODB_APP_AGENT_CAPABILITIES_MAX = 8;
381
+ var MINDOODB_APP_AGENT_CAPABILITY_TITLE_MAX = 80;
382
+ var MINDOODB_APP_AGENT_CAPABILITY_TOOLS_MAX = 64;
383
+ var MINDOODB_APP_AGENT_LIST_MAX = 8;
384
+ var MINDOODB_APP_AGENT_EXAMPLE_MAX = 200;
385
+ var MINDOODB_APP_AGENT_LIMIT_MAX = 300;
386
+ var MINDOODB_APP_AGENT_GUIDE_MAX_BYTES = 8 * 1024;
387
+ var MINDOODB_APP_AGENT_TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]{0,47}$/;
89
388
  var LOGICAL_DATABASE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/i;
90
- function isPlainObject(value) {
389
+ function isPlainObject2(value) {
91
390
  return typeof value === "object" && value !== null && !Array.isArray(value);
92
391
  }
93
392
  function readOptionalString(raw, key, errors) {
@@ -118,7 +417,7 @@ function readStringRecord(raw, key, errors) {
118
417
  if (value === void 0 || value === null) {
119
418
  return void 0;
120
419
  }
121
- if (!isPlainObject(value)) {
420
+ if (!isPlainObject2(value)) {
122
421
  errors.push(`App definition ${key} must be an object of string values.`);
123
422
  return void 0;
124
423
  }
@@ -184,7 +483,7 @@ function readDatabases(value, errors) {
184
483
  const result = [];
185
484
  const seen = /* @__PURE__ */ new Set();
186
485
  value.forEach((entry, index) => {
187
- if (!isPlainObject(entry)) {
486
+ if (!isPlainObject2(entry)) {
188
487
  errors.push(`App definition database #${index} must be an object.`);
189
488
  return;
190
489
  }
@@ -237,7 +536,7 @@ function readLocalizedText(value, label, maxLength, errors) {
237
536
  }
238
537
  return trimmed || void 0;
239
538
  }
240
- if (!isPlainObject(value)) {
539
+ if (!isPlainObject2(value)) {
241
540
  errors.push(`${label} must be a string or an object of per-locale strings.`);
242
541
  return void 0;
243
542
  }
@@ -284,7 +583,7 @@ function readAccepts(value, errors) {
284
583
  const ids = /* @__PURE__ */ new Set();
285
584
  value.forEach((entry, index) => {
286
585
  const label = `App definition accepts[${index}]`;
287
- if (!isPlainObject(entry)) {
586
+ if (!isPlainObject2(entry)) {
288
587
  errors.push(`${label} must be an object.`);
289
588
  return;
290
589
  }
@@ -345,7 +644,7 @@ var COMPONENT_FIELD_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;
345
644
  var COMPONENT_INTENTS = ["create", "edit", "view"];
346
645
  var COMPONENT_CREATE_MAX_BYTES = 16 * 1024;
347
646
  function readComponentFieldMatch(value, label, errors) {
348
- if (!isPlainObject(value)) {
647
+ if (!isPlainObject2(value)) {
349
648
  errors.push(`${label} must be an object of field values.`);
350
649
  return void 0;
351
650
  }
@@ -368,6 +667,28 @@ var MINDOODB_APP_COMPONENT_CONTRACT_PATTERN = /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]
368
667
  var COMPONENT_CONTRACTS_MAX = 8;
369
668
  var COMPONENT_REFERENCES_MAX = 8;
370
669
  var COMPONENT_REFERENCE_SHOW_MAX = 8;
670
+ var COMPONENT_SUPPORTS_MAX = 16;
671
+ function readComponentSupports(value, label, errors) {
672
+ if (value === void 0) {
673
+ return void 0;
674
+ }
675
+ if (!Array.isArray(value) || value.length > COMPONENT_SUPPORTS_MAX) {
676
+ errors.push(`${label} must be an array of at most ${COMPONENT_SUPPORTS_MAX} entries.`);
677
+ return void 0;
678
+ }
679
+ const result = [];
680
+ for (const entry of value) {
681
+ const text = typeof entry === "string" ? entry.trim() : "";
682
+ if (!isMindooDBAppSupportsEntry(text, MINDOODB_APP_COMPONENT_CONTRACT_PATTERN)) {
683
+ errors.push(`${label} entries must look like "validate" or "inspect:mindoo.inspect.document@1", received ${JSON.stringify(entry)}.`);
684
+ return void 0;
685
+ }
686
+ if (!result.includes(text)) {
687
+ result.push(text);
688
+ }
689
+ }
690
+ return result.length ? result : void 0;
691
+ }
371
692
  function readComponentContracts(value, label, errors) {
372
693
  if (value === void 0) {
373
694
  return void 0;
@@ -378,14 +699,14 @@ function readComponentContracts(value, label, errors) {
378
699
  }
379
700
  const result = [];
380
701
  for (const [index, entry] of value.entries()) {
381
- const contract = isPlainObject(entry) && typeof entry.contract === "string" ? entry.contract.trim() : "";
702
+ const contract = isPlainObject2(entry) && typeof entry.contract === "string" ? entry.contract.trim() : "";
382
703
  if (!MINDOODB_APP_COMPONENT_CONTRACT_PATTERN.test(contract)) {
383
704
  errors.push(`${label}[${index}].contract must look like "mindoo.contacts.company@1".`);
384
705
  return void 0;
385
706
  }
386
707
  let fields;
387
- if (isPlainObject(entry) && entry.fields !== void 0) {
388
- if (!isPlainObject(entry.fields)) {
708
+ if (isPlainObject2(entry) && entry.fields !== void 0) {
709
+ if (!isPlainObject2(entry.fields)) {
389
710
  errors.push(`${label}[${index}].fields must map contract fields to document fields.`);
390
711
  return void 0;
391
712
  }
@@ -414,7 +735,7 @@ function readComponentReferences(value, label, rootMatch, errors) {
414
735
  const fieldsSeen = /* @__PURE__ */ new Set();
415
736
  for (const [index, entry] of value.entries()) {
416
737
  const at = `${label}[${index}]`;
417
- if (!isPlainObject(entry)) {
738
+ if (!isPlainObject2(entry)) {
418
739
  errors.push(`${at} must be an object.`);
419
740
  return void 0;
420
741
  }
@@ -463,7 +784,7 @@ function readComponents(value, errors) {
463
784
  value.forEach((entry, index) => {
464
785
  const label = `App definition components[${index}]`;
465
786
  const errorCount = errors.length;
466
- if (!isPlainObject(entry)) {
787
+ if (!isPlainObject2(entry)) {
467
788
  errors.push(`${label} must be an object.`);
468
789
  return;
469
790
  }
@@ -510,7 +831,7 @@ function readComponents(value, errors) {
510
831
  }
511
832
  let create;
512
833
  if (entry.create !== void 0) {
513
- if (!isPlainObject(entry.create)) {
834
+ if (!isPlainObject2(entry.create)) {
514
835
  errors.push(`${label}.create must be an object of initial field values.`);
515
836
  return;
516
837
  }
@@ -539,7 +860,7 @@ function readComponents(value, errors) {
539
860
  }
540
861
  let children;
541
862
  if (entry.children !== void 0) {
542
- if (!isPlainObject(entry.children)) {
863
+ if (!isPlainObject2(entry.children)) {
543
864
  errors.push(`${label}.children must be an object.`);
544
865
  return;
545
866
  }
@@ -568,6 +889,7 @@ function readComponents(value, errors) {
568
889
  }
569
890
  const provides = readComponentContracts(entry.provides, `${label}.provides`, errors);
570
891
  const references = readComponentReferences(entry.references, `${label}.references`, match, errors);
892
+ const supports = readComponentSupports(entry.supports, `${label}.supports`, errors);
571
893
  if (errors.length !== errorCount) {
572
894
  return;
573
895
  }
@@ -582,7 +904,8 @@ function readComponents(value, errors) {
582
904
  ...children ? { children } : {},
583
905
  ...category ? { category } : {},
584
906
  ...provides ? { provides } : {},
585
- ...references ? { references } : {}
907
+ ...references ? { references } : {},
908
+ ...supports ? { supports } : {}
586
909
  });
587
910
  });
588
911
  return result.length ? result : void 0;
@@ -622,7 +945,7 @@ function readListing(value, errors) {
622
945
  if (value === void 0 || value === null) {
623
946
  return void 0;
624
947
  }
625
- if (!isPlainObject(value)) {
948
+ if (!isPlainObject2(value)) {
626
949
  errors.push("App definition listing must be an object.");
627
950
  return void 0;
628
951
  }
@@ -662,7 +985,7 @@ function readListing(value, errors) {
662
985
  value.screenshots.forEach((entry, index) => {
663
986
  const label = `App definition listing.screenshots[${index}]`;
664
987
  const raw = typeof entry === "string" ? { file: entry } : entry;
665
- if (!isPlainObject(raw)) {
988
+ if (!isPlainObject2(raw)) {
666
989
  errors.push(`${label} must be a path or an object with a file.`);
667
990
  return;
668
991
  }
@@ -677,7 +1000,7 @@ function readListing(value, errors) {
677
1000
  }
678
1001
  }
679
1002
  if (value.publisher !== void 0 && value.publisher !== null) {
680
- const publisher = isPlainObject(value.publisher) ? value.publisher : {};
1003
+ const publisher = isPlainObject2(value.publisher) ? value.publisher : {};
681
1004
  const name = typeof publisher.name === "string" ? publisher.name.trim() : "";
682
1005
  if (!name) {
683
1006
  errors.push("App definition listing.publisher must be an object with a non-empty name.");
@@ -692,6 +1015,163 @@ function readListing(value, errors) {
692
1015
  }
693
1016
  return Object.keys(listing).length ? listing : void 0;
694
1017
  }
1018
+ var AGENT_CAPABILITY_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,47}$/;
1019
+ var AGENT_LOCALE_PATTERN = /^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/;
1020
+ var AGENT_GUIDE_PATH_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9_.\/-]{0,199}\.md$/;
1021
+ function readAgentLocaleText(value, label, maxLength, errors) {
1022
+ if (!isPlainObject2(value)) {
1023
+ errors.push(`${label} must be an object of per-locale strings with an "en" entry.`);
1024
+ return void 0;
1025
+ }
1026
+ const result = {};
1027
+ for (const [locale, text] of Object.entries(value)) {
1028
+ if (!AGENT_LOCALE_PATTERN.test(locale)) {
1029
+ errors.push(`${label} has an invalid locale ${JSON.stringify(locale)}.`);
1030
+ return void 0;
1031
+ }
1032
+ const trimmed = typeof text === "string" ? text.trim() : "";
1033
+ if (!trimmed) {
1034
+ errors.push(`${label}.${locale} must be a non-empty string.`);
1035
+ return void 0;
1036
+ }
1037
+ if (trimmed.length > maxLength) {
1038
+ errors.push(`${label}.${locale} must not be longer than ${maxLength} characters.`);
1039
+ return void 0;
1040
+ }
1041
+ result[locale] = trimmed;
1042
+ }
1043
+ if (!result.en) {
1044
+ errors.push(`${label} must include an "en" entry as the fallback for other locales.`);
1045
+ return void 0;
1046
+ }
1047
+ return result;
1048
+ }
1049
+ function readAgentLocaleList(value, label, maxLength, errors) {
1050
+ if (value === void 0) {
1051
+ return void 0;
1052
+ }
1053
+ if (!isPlainObject2(value)) {
1054
+ errors.push(`${label} must be an object of per-locale string arrays with an "en" entry.`);
1055
+ return void 0;
1056
+ }
1057
+ const result = {};
1058
+ for (const [locale, entries] of Object.entries(value)) {
1059
+ if (!AGENT_LOCALE_PATTERN.test(locale)) {
1060
+ errors.push(`${label} has an invalid locale ${JSON.stringify(locale)}.`);
1061
+ return void 0;
1062
+ }
1063
+ if (!Array.isArray(entries) || !entries.length || entries.length > MINDOODB_APP_AGENT_LIST_MAX) {
1064
+ errors.push(`${label}.${locale} must be an array of 1-${MINDOODB_APP_AGENT_LIST_MAX} strings.`);
1065
+ return void 0;
1066
+ }
1067
+ const list = [];
1068
+ for (const entry of entries) {
1069
+ const trimmed = typeof entry === "string" ? entry.trim() : "";
1070
+ if (!trimmed || trimmed.length > maxLength) {
1071
+ errors.push(`${label}.${locale} must only hold non-empty strings of at most ${maxLength} characters.`);
1072
+ return void 0;
1073
+ }
1074
+ list.push(trimmed);
1075
+ }
1076
+ result[locale] = list;
1077
+ }
1078
+ if (!result.en) {
1079
+ errors.push(`${label} must include an "en" entry as the fallback for other locales.`);
1080
+ return void 0;
1081
+ }
1082
+ return result;
1083
+ }
1084
+ function readAgentCapabilities(value, errors) {
1085
+ const label = "App definition agent.capabilities";
1086
+ if (!Array.isArray(value) || !value.length || value.length > MINDOODB_APP_AGENT_CAPABILITIES_MAX) {
1087
+ errors.push(`${label} must be an array of 1-${MINDOODB_APP_AGENT_CAPABILITIES_MAX} capabilities.`);
1088
+ return void 0;
1089
+ }
1090
+ const result = [];
1091
+ const ids = /* @__PURE__ */ new Set();
1092
+ for (const [index, entry] of value.entries()) {
1093
+ const at = `${label}[${index}]`;
1094
+ if (!isPlainObject2(entry)) {
1095
+ errors.push(`${at} must be an object.`);
1096
+ return void 0;
1097
+ }
1098
+ const id = typeof entry.id === "string" ? entry.id.trim() : "";
1099
+ if (!AGENT_CAPABILITY_ID_PATTERN.test(id)) {
1100
+ errors.push(`${at}.id must be 1-48 lowercase letters, digits, "-" or "_", received ${JSON.stringify(entry.id)}.`);
1101
+ return void 0;
1102
+ }
1103
+ if (ids.has(id)) {
1104
+ errors.push(`${at}.id "${id}" is used twice.`);
1105
+ return void 0;
1106
+ }
1107
+ ids.add(id);
1108
+ const title = readAgentLocaleText(entry.title, `${at}.title`, MINDOODB_APP_AGENT_CAPABILITY_TITLE_MAX, errors);
1109
+ if (!title) {
1110
+ return void 0;
1111
+ }
1112
+ if (!Array.isArray(entry.tools) || !entry.tools.length || entry.tools.length > MINDOODB_APP_AGENT_CAPABILITY_TOOLS_MAX) {
1113
+ errors.push(`${at}.tools must be an array of 1-${MINDOODB_APP_AGENT_CAPABILITY_TOOLS_MAX} tool names.`);
1114
+ return void 0;
1115
+ }
1116
+ const tools = [];
1117
+ for (const tool of entry.tools) {
1118
+ const name = typeof tool === "string" ? tool.trim() : "";
1119
+ if (!MINDOODB_APP_AGENT_TOOL_NAME_PATTERN.test(name) || /^haven(?:_|$)/.test(name)) {
1120
+ errors.push(
1121
+ `${at}.tools contains ${JSON.stringify(tool)}; name the app's own tools as registered, without prefix and never "haven_*".`
1122
+ );
1123
+ return void 0;
1124
+ }
1125
+ if (!tools.includes(name)) {
1126
+ tools.push(name);
1127
+ }
1128
+ }
1129
+ result.push({ id, title, tools });
1130
+ }
1131
+ return result;
1132
+ }
1133
+ function readAgentProfile(value, errors) {
1134
+ if (value === void 0 || value === null) {
1135
+ return void 0;
1136
+ }
1137
+ if (!isPlainObject2(value)) {
1138
+ errors.push("App definition agent must be an object.");
1139
+ return void 0;
1140
+ }
1141
+ const errorCount = errors.length;
1142
+ const summary = readAgentLocaleText(value.summary, "App definition agent.summary", MINDOODB_APP_AGENT_SUMMARY_MAX, errors);
1143
+ const capabilities = readAgentCapabilities(value.capabilities, errors);
1144
+ const examples = readAgentLocaleList(value.examples, "App definition agent.examples", MINDOODB_APP_AGENT_EXAMPLE_MAX, errors);
1145
+ const limits = readAgentLocaleList(value.limits, "App definition agent.limits", MINDOODB_APP_AGENT_LIMIT_MAX, errors);
1146
+ let guide;
1147
+ if (value.guide !== void 0) {
1148
+ guide = readAgentLocaleText(value.guide, "App definition agent.guide", 200, errors);
1149
+ for (const [locale, path] of Object.entries(guide ?? {})) {
1150
+ if (!AGENT_GUIDE_PATH_PATTERN.test(path) || path.split("/").some((part) => part === "." || part === "..")) {
1151
+ errors.push(
1152
+ `App definition agent.guide.${locale} must be a relative path to a .md file next to the manifest, e.g. "agent/agent.${locale}.md".`
1153
+ );
1154
+ guide = void 0;
1155
+ break;
1156
+ }
1157
+ }
1158
+ }
1159
+ if (errors.length !== errorCount || !summary || !capabilities) {
1160
+ return void 0;
1161
+ }
1162
+ return {
1163
+ summary,
1164
+ capabilities,
1165
+ ...examples ? { examples } : {},
1166
+ ...limits ? { limits } : {},
1167
+ ...guide ? { guide } : {}
1168
+ };
1169
+ }
1170
+ function validateMindooDBAppAgentProfile(value) {
1171
+ const errors = [];
1172
+ const agent = readAgentProfile(value, errors);
1173
+ return { agent: errors.length ? void 0 : agent, errors };
1174
+ }
695
1175
  function resolveMindooDBAppLocalizedText(text, locale) {
696
1176
  if (text === void 0) {
697
1177
  return "";
@@ -717,7 +1197,7 @@ function resolveMindooDBAppListingAssetUrl(path, originUrl) {
717
1197
  }
718
1198
  function validateMindooDBAppDefinition(raw) {
719
1199
  const errors = [];
720
- if (!isPlainObject(raw)) {
1200
+ if (!isPlainObject2(raw)) {
721
1201
  return { definition: null, errors: ["App definition must be a JSON object."] };
722
1202
  }
723
1203
  if (raw.format !== MINDOODB_APP_DEFINITION_FORMAT) {
@@ -772,6 +1252,7 @@ function validateMindooDBAppDefinition(raw) {
772
1252
  const listing = readListing(raw.listing, errors);
773
1253
  const accepts = readAccepts(raw.accepts, errors);
774
1254
  const components = readComponents(raw.components, errors);
1255
+ const agent = readAgentProfile(raw.agent, errors);
775
1256
  const agentToolPrefix = readOptionalString(raw, "agentToolPrefix", errors);
776
1257
  if (agentToolPrefix !== void 0 && (!/^[a-z][a-z0-9_]{0,15}$/.test(agentToolPrefix) || agentToolPrefix.endsWith("_") || /^haven(?:_|$)/.test(agentToolPrefix))) {
777
1258
  errors.push(
@@ -813,7 +1294,8 @@ function validateMindooDBAppDefinition(raw) {
813
1294
  databases,
814
1295
  accepts,
815
1296
  components,
816
- listing
1297
+ listing,
1298
+ agent
817
1299
  },
818
1300
  errors: []
819
1301
  };
@@ -1229,29 +1711,29 @@ function bindDragSource(element, options, start, follow) {
1229
1711
  }
1230
1712
 
1231
1713
  // src/client/agentInput.ts
1232
- function isPlainObject2(value) {
1714
+ function isPlainObject3(value) {
1233
1715
  return typeof value === "object" && value !== null && !Array.isArray(value);
1234
1716
  }
1235
1717
  function isPlaceholder(value) {
1236
1718
  if (value === null || value === void 0) return true;
1237
1719
  if (typeof value === "string") return value.trim() === "";
1238
1720
  if (Array.isArray(value)) return value.length === 0;
1239
- if (isPlainObject2(value)) return Object.keys(value).length === 0;
1721
+ if (isPlainObject3(value)) return Object.keys(value).length === 0;
1240
1722
  return false;
1241
1723
  }
1242
1724
  function normalizeValue(value, schema) {
1243
- if (!isPlainObject2(schema)) return value;
1725
+ if (!isPlainObject3(schema)) return value;
1244
1726
  if (Array.isArray(value)) {
1245
1727
  const items = schema.items;
1246
- return isPlainObject2(items) ? value.map((item) => normalizeValue(item, items)) : value;
1728
+ return isPlainObject3(items) ? value.map((item) => normalizeValue(item, items)) : value;
1247
1729
  }
1248
- if (isPlainObject2(value) && isPlainObject2(schema.properties)) {
1730
+ if (isPlainObject3(value) && isPlainObject3(schema.properties)) {
1249
1731
  return normalizeObject(value, schema);
1250
1732
  }
1251
1733
  return value;
1252
1734
  }
1253
1735
  function normalizeObject(input, schema) {
1254
- const properties = isPlainObject2(schema.properties) ? schema.properties : {};
1736
+ const properties = isPlainObject3(schema.properties) ? schema.properties : {};
1255
1737
  const required = new Set(Array.isArray(schema.required) ? schema.required.filter((key) => typeof key === "string") : []);
1256
1738
  const result = {};
1257
1739
  for (const [key, raw] of Object.entries(input)) {
@@ -1266,7 +1748,7 @@ function normalizeObject(input, schema) {
1266
1748
  return result;
1267
1749
  }
1268
1750
  function normalizeAgentToolInput(input, schema) {
1269
- return isPlainObject2(input) ? normalizeObject(input, schema) : input;
1751
+ return isPlainObject3(input) ? normalizeObject(input, schema) : input;
1270
1752
  }
1271
1753
 
1272
1754
  // src/client/agentTools.ts
@@ -1483,6 +1965,15 @@ import { parseMindooDBFormulaBooleanExpression } from "mindoodb-view-language";
1483
1965
  function isEmbedEventMessage(message) {
1484
1966
  return message.kind === "embed-event";
1485
1967
  }
1968
+ function isEmbedRequestMessage(message) {
1969
+ return message.kind === "embed-request";
1970
+ }
1971
+ function isMethodNotFound(error) {
1972
+ return error instanceof Error && error.name === "method-not-found";
1973
+ }
1974
+ function errorMessage(error) {
1975
+ return error instanceof Error ? error.message : String(error);
1976
+ }
1486
1977
  function isEmbeddingRequestMessage(message) {
1487
1978
  return message.kind === "embedding-request";
1488
1979
  }
@@ -1549,13 +2040,14 @@ function createComponentFrame(container, url, allow) {
1549
2040
  return frame;
1550
2041
  }
1551
2042
  var MindooDBAppEmbedImpl = class {
1552
- constructor(rpc, embedId, componentKey, databaseId, docId, frame, container) {
2043
+ constructor(rpc, embedId, componentKey, databaseId, docId, frame, container, supports = []) {
1553
2044
  this.rpc = rpc;
1554
2045
  this.embedId = embedId;
1555
2046
  this.componentKey = componentKey;
1556
2047
  this.databaseId = databaseId;
1557
2048
  this.docId = docId;
1558
2049
  this.frame = frame;
2050
+ this.supports = supports;
1559
2051
  this.closed = new Promise((resolve) => {
1560
2052
  this.resolveClosed = resolve;
1561
2053
  });
@@ -1572,6 +2064,7 @@ var MindooDBAppEmbedImpl = class {
1572
2064
  databaseId;
1573
2065
  docId;
1574
2066
  frame;
2067
+ supports;
1575
2068
  closed;
1576
2069
  resolveClosed;
1577
2070
  closedEvent = null;
@@ -1581,6 +2074,8 @@ var MindooDBAppEmbedImpl = class {
1581
2074
  tracker = null;
1582
2075
  toolsState = null;
1583
2076
  toolsListeners = /* @__PURE__ */ new Set();
2077
+ beforeSaveHandler = null;
2078
+ savedListeners = /* @__PURE__ */ new Set();
1584
2079
  get placement() {
1585
2080
  return this.frame ? "frame" : "overlay";
1586
2081
  }
@@ -1663,6 +2158,88 @@ var MindooDBAppEmbedImpl = class {
1663
2158
  const stopClosed = this.onClosed(() => finish(null));
1664
2159
  });
1665
2160
  }
2161
+ async inspect(request) {
2162
+ const result = await this.rpc.call("embeds.inspect", {
2163
+ embedId: this.embedId,
2164
+ request: normalizeMindooDBAppInspectRequest(request)
2165
+ });
2166
+ return normalizeMindooDBAppInspection(result);
2167
+ }
2168
+ onBeforeSave(handler, options) {
2169
+ this.beforeSaveHandler = handler;
2170
+ this.announceBeforeSave(true, options?.inspect);
2171
+ return () => {
2172
+ if (this.beforeSaveHandler === handler) {
2173
+ this.beforeSaveHandler = null;
2174
+ this.announceBeforeSave(false);
2175
+ }
2176
+ };
2177
+ }
2178
+ /** Haven only asks hosts that said they check, and fetches the inspection they want. */
2179
+ announceBeforeSave(enabled, inspect) {
2180
+ if (this.closedEvent) {
2181
+ return;
2182
+ }
2183
+ void this.rpc.call("embeds.setBeforeSave", {
2184
+ embedId: this.embedId,
2185
+ enabled,
2186
+ ...enabled ? { inspect: normalizeMindooDBAppInspectRequest(inspect) } : {}
2187
+ }).catch((error) => {
2188
+ if (!isMethodNotFound(error)) {
2189
+ console.warn("[mindoodb-app-sdk] Could not register the save check.", error);
2190
+ }
2191
+ });
2192
+ }
2193
+ /** Haven asks before the component saves: run the handler, never longer than Haven waits. */
2194
+ async answerBeforeSave(params) {
2195
+ const handler = this.beforeSaveHandler;
2196
+ if (!handler || this.closedEvent) {
2197
+ return { issues: [] };
2198
+ }
2199
+ const result = await handler({
2200
+ embedId: this.embedId,
2201
+ inspection: params?.inspection ?? null,
2202
+ root: params?.root ?? null
2203
+ });
2204
+ return { issues: normalizeMindooDBAppIssues(result?.issues) };
2205
+ }
2206
+ onAfterSave(listener) {
2207
+ this.savedListeners.add(listener);
2208
+ return () => {
2209
+ this.savedListeners.delete(listener);
2210
+ };
2211
+ }
2212
+ /** The component reported that it saved. */
2213
+ notifySaved() {
2214
+ if (this.closedEvent) {
2215
+ return;
2216
+ }
2217
+ const event = { embedId: this.embedId };
2218
+ this.savedListeners.forEach((listener) => {
2219
+ try {
2220
+ listener(event);
2221
+ } catch (error) {
2222
+ console.error("MindooDB embed saved listener failed.", error);
2223
+ }
2224
+ });
2225
+ }
2226
+ async showIssues(issues) {
2227
+ await this.rpc.call("embeds.showIssues", { embedId: this.embedId, issues: normalizeMindooDBAppIssues(issues) });
2228
+ }
2229
+ async reveal(anchor) {
2230
+ const normalized = normalizeMindooDBAppInspectAnchor(anchor);
2231
+ if (!normalized) {
2232
+ throw new Error("Invalid anchor.");
2233
+ }
2234
+ await this.rpc.call("embeds.reveal", { embedId: this.embedId, anchor: normalized });
2235
+ }
2236
+ async callTool(name, input) {
2237
+ return await this.rpc.call("embeds.callTool", {
2238
+ embedId: this.embedId,
2239
+ name: String(name),
2240
+ input: input === void 0 ? {} : JSON.parse(JSON.stringify(input))
2241
+ });
2242
+ }
1666
2243
  async setRect(rect) {
1667
2244
  if (this.closedEvent) {
1668
2245
  return;
@@ -1717,6 +2294,8 @@ var MindooDBAppEmbedImpl = class {
1717
2294
  });
1718
2295
  this.listeners.clear();
1719
2296
  this.dirtyListeners.clear();
2297
+ this.savedListeners.clear();
2298
+ this.beforeSaveHandler = null;
1720
2299
  this.toolsState = null;
1721
2300
  this.toolsListeners.forEach((listener) => {
1722
2301
  try {
@@ -1736,6 +2315,10 @@ var MindooDBAppEmbedsClient = class {
1736
2315
  void this.answerRequest(message);
1737
2316
  return;
1738
2317
  }
2318
+ if (isEmbedRequestMessage(message)) {
2319
+ void this.answerEmbedRequest(message);
2320
+ return;
2321
+ }
1739
2322
  if (!isEmbedEventMessage(message)) {
1740
2323
  return;
1741
2324
  }
@@ -1759,6 +2342,10 @@ var MindooDBAppEmbedsClient = class {
1759
2342
  }
1760
2343
  return;
1761
2344
  }
2345
+ if (message.event?.type === "saved") {
2346
+ this.open.get(message.event.embedId)?.notifySaved();
2347
+ return;
2348
+ }
1762
2349
  if (message.event?.type !== "closed") {
1763
2350
  return;
1764
2351
  }
@@ -1796,7 +2383,8 @@ var MindooDBAppEmbedsClient = class {
1796
2383
  input.databaseId,
1797
2384
  input.docId,
1798
2385
  frame,
1799
- container
2386
+ container,
2387
+ Array.isArray(response.supports) ? response.supports.filter((entry) => typeof entry === "string") : []
1800
2388
  );
1801
2389
  const earlyDirty = this.earlyDirty.get(embed.embedId);
1802
2390
  if (earlyDirty !== void 0) {
@@ -1872,7 +2460,45 @@ var MindooDBAppEmbedsClient = class {
1872
2460
  this.saveHandler = null;
1873
2461
  }
1874
2462
  };
1875
- }
2463
+ },
2464
+ provideInspection: (provider) => {
2465
+ this.inspectionProvider = provider;
2466
+ return () => {
2467
+ if (this.inspectionProvider === provider) {
2468
+ this.inspectionProvider = null;
2469
+ }
2470
+ };
2471
+ },
2472
+ onShowIssues: (handler) => {
2473
+ this.showIssuesHandler = handler;
2474
+ return () => {
2475
+ if (this.showIssuesHandler === handler) {
2476
+ this.showIssuesHandler = null;
2477
+ }
2478
+ };
2479
+ },
2480
+ onReveal: (handler) => {
2481
+ this.revealHandler = handler;
2482
+ return () => {
2483
+ if (this.revealHandler === handler) {
2484
+ this.revealHandler = null;
2485
+ }
2486
+ };
2487
+ },
2488
+ validate: async (options) => await this.validate(options),
2489
+ save: async (flush, options) => await performMindooDBAppEmbeddingSave({
2490
+ validate: () => this.validate(options),
2491
+ provider: this.inspectionProvider,
2492
+ showIssues: this.showIssuesHandler,
2493
+ flush,
2494
+ // Only news for the host: a lost message must not fail a save that happened.
2495
+ saved: () => this.rpc.call("embedding.saved", {}).then(
2496
+ () => {
2497
+ },
2498
+ () => {
2499
+ }
2500
+ )
2501
+ })
1876
2502
  };
1877
2503
  }
1878
2504
  rpc;
@@ -1887,18 +2513,53 @@ var MindooDBAppEmbedsClient = class {
1887
2513
  stopListening;
1888
2514
  /** This app as a component: what to do when its host asks it to save. */
1889
2515
  saveHandler = null;
1890
- /** Runs the save handler and tells Haven how it went; Haven answers the host. */
2516
+ inspectionProvider = null;
2517
+ showIssuesHandler = null;
2518
+ revealHandler = null;
2519
+ /** `embedding.validate`; ok when Haven cannot check (not embedded, older Haven). */
2520
+ async validate(options) {
2521
+ try {
2522
+ const result = await this.rpc.call("embedding.validate", {
2523
+ interactive: options?.interactive !== false
2524
+ });
2525
+ return {
2526
+ ok: result?.ok !== false,
2527
+ issues: normalizeMindooDBAppIssues(result?.issues),
2528
+ ...result?.timedOut ? { timedOut: true } : {}
2529
+ };
2530
+ } catch (error) {
2531
+ if (isMethodNotFound(error) || error instanceof Error && error.name === "unsupported") {
2532
+ return { ok: true, issues: [] };
2533
+ }
2534
+ throw error;
2535
+ }
2536
+ }
2537
+ /** Runs the matching handler and tells Haven how it went; Haven answers the host. */
1891
2538
  async answerRequest(message) {
1892
2539
  let response;
1893
- if (message.request !== "save" || !this.saveHandler) {
1894
- response = { ok: false, error: "unsupported" };
1895
- } else {
1896
- try {
2540
+ try {
2541
+ const params = message.params ?? {};
2542
+ if (message.request === "save" && this.saveHandler) {
1897
2543
  await this.saveHandler();
1898
2544
  response = { ok: true };
1899
- } catch (error) {
1900
- response = { ok: false, error: error instanceof Error ? error.message : String(error) };
2545
+ } else if (message.request === "inspect" && this.inspectionProvider) {
2546
+ const inspection = await this.inspectionProvider(normalizeMindooDBAppInspectRequest(params.request));
2547
+ response = { ok: true, result: normalizeMindooDBAppInspection(inspection) };
2548
+ } else if (message.request === "showIssues" && this.showIssuesHandler) {
2549
+ await this.showIssuesHandler(normalizeMindooDBAppIssues(params.issues));
2550
+ response = { ok: true };
2551
+ } else if (message.request === "reveal" && this.revealHandler) {
2552
+ const anchor = normalizeMindooDBAppInspectAnchor(params.anchor);
2553
+ if (!anchor) {
2554
+ throw new Error("Invalid anchor.");
2555
+ }
2556
+ await this.revealHandler(anchor);
2557
+ response = { ok: true };
2558
+ } else {
2559
+ response = { ok: false, error: "unsupported" };
1901
2560
  }
2561
+ } catch (error) {
2562
+ response = { ok: false, error: errorMessage(error) };
1902
2563
  }
1903
2564
  try {
1904
2565
  await this.rpc.call("embedding.respond", { requestId: message.requestId, ...response });
@@ -1906,6 +2567,24 @@ var MindooDBAppEmbedsClient = class {
1906
2567
  console.warn("[mindoodb-app-sdk] Could not answer the host's request.", error);
1907
2568
  }
1908
2569
  }
2570
+ /** This app as a host: Haven asks before one of its components saves. */
2571
+ async answerEmbedRequest(message) {
2572
+ let response;
2573
+ const embed = this.open.get(message.embedId);
2574
+ try {
2575
+ response = message.request === "beforeSave" ? { ok: true, result: embed ? await embed.answerBeforeSave(message.params) : { issues: [] } } : { ok: false, error: "unsupported" };
2576
+ } catch (error) {
2577
+ response = {
2578
+ ok: true,
2579
+ result: { issues: [{ severity: "warning", message: `The check failed: ${errorMessage(error)}`, code: "check-failed" }] }
2580
+ };
2581
+ }
2582
+ try {
2583
+ await this.rpc.call("embeds.respond", { requestId: message.requestId, ...response });
2584
+ } catch (error) {
2585
+ console.warn("[mindoodb-app-sdk] Could not answer Haven's request.", error);
2586
+ }
2587
+ }
1909
2588
  dispose() {
1910
2589
  this.stopListening();
1911
2590
  }
@@ -3739,6 +4418,27 @@ export {
3739
4418
  isValidMindooDBDocumentId,
3740
4419
  mindooDBDocumentId,
3741
4420
  assertValidMindooDBCreateIds,
4421
+ MINDOODB_INSPECT_DOCUMENT,
4422
+ MINDOODB_INSPECT_SPREADSHEET,
4423
+ MINDOODB_INSPECT_SLIDES,
4424
+ MINDOODB_APP_INSPECTION_FIELD,
4425
+ MINDOODB_APP_INSPECTION_SUMMARY_MAX_BYTES,
4426
+ MINDOODB_APP_INSPECTION_MAX_BYTES,
4427
+ MINDOODB_APP_ISSUES_MAX,
4428
+ MindooDBAppEmbedValidationError,
4429
+ mindooDBAppComponentSupports,
4430
+ mindooDBAppInspectContracts,
4431
+ normalizeMindooDBAppInspectAnchor,
4432
+ normalizeMindooDBAppIssues,
4433
+ normalizeMindooDBAppInspectRequest,
4434
+ normalizeMindooDBAppInspection,
4435
+ summarizeMindooDBAppInspection,
4436
+ mindooDBAppInspectionSummaryValue,
4437
+ readMindooDBAppInspectionSummary,
4438
+ defineDocumentRules,
4439
+ mindooDBAppInspectRules,
4440
+ performMindooDBAppEmbeddingSave,
4441
+ resolveMindooDBAppEmbedValidation,
3742
4442
  MINDOODB_APP_DEFINITION_FORMAT,
3743
4443
  MINDOODB_APP_DEFINITION_VERSION,
3744
4444
  MINDOODB_APP_DEFINITION_FILE_NAME,
@@ -3747,6 +4447,15 @@ export {
3747
4447
  MINDOODB_APP_LISTING_SUMMARY_MAX,
3748
4448
  MINDOODB_APP_LISTING_DESCRIPTION_MAX,
3749
4449
  MINDOODB_APP_LISTING_MAX_SCREENSHOTS,
4450
+ MINDOODB_APP_AGENT_SUMMARY_MAX,
4451
+ MINDOODB_APP_AGENT_CAPABILITIES_MAX,
4452
+ MINDOODB_APP_AGENT_CAPABILITY_TITLE_MAX,
4453
+ MINDOODB_APP_AGENT_CAPABILITY_TOOLS_MAX,
4454
+ MINDOODB_APP_AGENT_LIST_MAX,
4455
+ MINDOODB_APP_AGENT_EXAMPLE_MAX,
4456
+ MINDOODB_APP_AGENT_LIMIT_MAX,
4457
+ MINDOODB_APP_AGENT_GUIDE_MAX_BYTES,
4458
+ MINDOODB_APP_AGENT_TOOL_NAME_PATTERN,
3750
4459
  MINDOODB_APP_ACCEPTS_MAX,
3751
4460
  validateMindooDBAppAccepts,
3752
4461
  mindooDBAppAcceptMatchesType,
@@ -3754,6 +4463,7 @@ export {
3754
4463
  MINDOODB_APP_COMPONENT_CONTRACT_PATTERN,
3755
4464
  validateMindooDBAppComponents,
3756
4465
  mindooDBAppComponentFieldsMatch,
4466
+ validateMindooDBAppAgentProfile,
3757
4467
  resolveMindooDBAppLocalizedText,
3758
4468
  resolveMindooDBAppListingAssetUrl,
3759
4469
  validateMindooDBAppDefinition,