@blinkk/root-cms 3.1.3 → 3.1.5
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/dist/app.js +3 -5
- package/dist/{chunk-4VZTYUQ7.js → chunk-6CTCV2PN.js} +192 -14
- package/dist/{chunk-AFBSITEO.js → chunk-ETHWZSNM.js} +4 -0
- package/dist/chunk-MUXSUGFF.js +764 -0
- package/dist/cli.js +1 -1
- package/dist/client.js +1 -1
- package/dist/core/ai-tools.d.ts +82 -42
- package/dist/core/ai.d.ts +54 -218
- package/dist/core/plugin.d.ts +10 -4
- package/dist/core/schema.d.ts +88 -3
- package/dist/core.js +1 -1
- package/dist/functions.js +2 -3
- package/dist/plugin.js +43 -209
- package/dist/shared/ai/models.d.ts +110 -0
- package/dist/shared/ai/prompt-utils.d.ts +59 -0
- package/dist/ui/AIPage-25WICIOT.js +1 -0
- package/dist/ui/AssetsPage-WKTM2J2G.js +1 -0
- package/dist/ui/CollectionPage-5ZOVG7IG.js +1 -0
- package/dist/ui/ComparePage-DDIFYYTK.js +1 -0
- package/dist/ui/DataPage-RFNGSDDN.js +1 -0
- package/dist/ui/DataSourcePage-U46CDIH2.js +1 -0
- package/dist/ui/DocTranslationsPage-BFCM2PE3.js +1 -0
- package/dist/ui/DocumentPage-OTBXM55S.js +1 -0
- package/dist/ui/EditDataSourcePage-NKKIF6AD.js +1 -0
- package/dist/ui/EditReleasePage-TKNOUT7A.js +1 -0
- package/dist/ui/EmbeddedAIPage-4AX7VO3T.js +1 -0
- package/dist/ui/EmbeddedDocumentPage-2CNQJTW5.js +1 -0
- package/dist/ui/{ImageEditorDialog-GGS4VFEA.js → ImageEditorDialog-YDKOGVJV.js} +1 -1
- package/dist/ui/LogsPage-SCECIAZH.js +1 -0
- package/dist/ui/NewDataSourcePage-FAOPK2RZ.js +1 -0
- package/dist/ui/NewReleasePage-HD6T6UV2.js +1 -0
- package/dist/ui/{NotFoundPage-WXEZQZK6.js → NotFoundPage-JRYFUENW.js} +1 -1
- package/dist/ui/ProjectPage-2WIMWCSX.js +1 -0
- package/dist/ui/ReleasePage-GUMEMLF6.js +1 -0
- package/dist/ui/ReleasesPage-AW6PICTQ.js +1 -0
- package/dist/ui/SettingsPage-KFLNZ356.js +1 -0
- package/dist/ui/{SidebarToolsPage-API53RRR.js → SidebarToolsPage-3R7BQ2F7.js} +1 -1
- package/dist/ui/TaskPage-GZGPKIL5.js +1 -0
- package/dist/ui/TasksPage-G3GBTV3L.js +1 -0
- package/dist/ui/TranslationsArbPage-K272JEAA.js +2 -0
- package/dist/ui/TranslationsEditPage-XWXPNKRQ.js +1 -0
- package/dist/ui/{TranslationsPage-NGGZB4L6.js → TranslationsPage-7KUHVTLK.js} +1 -1
- package/dist/ui/ai-tools-7S4URTMT.js +1 -0
- package/dist/ui/{chunk-TVYAZN2Q.js → chunk-2FQMT5AB.js} +1 -1
- package/dist/ui/{chunk-J5E457OI.js → chunk-2PTLQRTU.js} +1 -1
- package/dist/ui/{chunk-UPDL6UXI.js → chunk-2RRM4HEQ.js} +1 -1
- package/dist/ui/{chunk-WYJJZTCI.js → chunk-34W6H4YG.js} +1 -1
- package/dist/ui/{chunk-4FGASIIX.js → chunk-44ZU5WMI.js} +1 -1
- package/dist/ui/{chunk-3E6CASIN.js → chunk-535JU7FU.js} +1 -1
- package/dist/ui/chunk-5KSGCGYY.js +1 -0
- package/dist/ui/{chunk-ZMS6NIGG.js → chunk-75NMQ3LW.js} +1 -1
- package/dist/ui/{chunk-Y3MCFLQU.js → chunk-7UHZS56B.js} +57 -57
- package/dist/ui/chunk-AAR7DBEN.js +110 -0
- package/dist/ui/{chunk-JS6TK4OP.js → chunk-ATTW36EM.js} +1 -1
- package/dist/ui/{chunk-DIFPCF7I.js → chunk-DWV5J2W7.js} +1 -1
- package/dist/ui/chunk-DZYYWCHX.js +3 -0
- package/dist/ui/chunk-F7RQT4XN.js +1 -0
- package/dist/ui/chunk-FVWSVOOY.js +1 -0
- package/dist/ui/chunk-GCSN3YEC.js +31 -0
- package/dist/ui/{chunk-CAY5NM4Z.js → chunk-H37RXS4R.js} +1 -1
- package/dist/ui/{chunk-JTIQBW33.js → chunk-HV3JJ5UT.js} +1 -1
- package/dist/ui/{chunk-MSYTAJBV.js → chunk-HXSB6YB2.js} +1 -1
- package/dist/ui/chunk-IGZDFHVM.js +1 -0
- package/dist/ui/chunk-ISUGBMXC.js +1 -0
- package/dist/ui/{chunk-G5ZZDHWA.js → chunk-JBLSUM6W.js} +1 -1
- package/dist/ui/{chunk-T77VOWHP.js → chunk-N5RJIILP.js} +1 -1
- package/dist/ui/{chunk-BW2MKGNP.js → chunk-NCZD5IWS.js} +1 -1
- package/dist/ui/chunk-NXWYS4HG.js +19 -0
- package/dist/ui/{chunk-FXIR2RBE.js → chunk-OWBT6YUM.js} +1 -1
- package/dist/ui/chunk-OWYV43BT.js +1 -0
- package/dist/ui/{chunk-QHJOTXYB.js → chunk-PIJ3E47R.js} +1 -1
- package/dist/ui/{chunk-ENQKSLGJ.js → chunk-PLYSJ7W5.js} +1 -1
- package/dist/ui/{chunk-FJLNXXE3.js → chunk-QFDU6FXP.js} +1 -1
- package/dist/ui/{chunk-P2Z66DHV.js → chunk-QLIIVG5Q.js} +1 -1
- package/dist/ui/{chunk-HARRKJFZ.js → chunk-QRAFYIAW.js} +1 -1
- package/dist/ui/{chunk-2EPQJUGM.js → chunk-QWB6MAPJ.js} +1 -1
- package/dist/ui/{chunk-W6LP22IK.js → chunk-RB23LLKL.js} +1 -1
- package/dist/ui/chunk-RN4XVVWD.js +1 -0
- package/dist/ui/{chunk-BOER3EAW.js → chunk-SYDHFYRC.js} +1 -1
- package/dist/ui/{chunk-NSI5JSVV.js → chunk-T5BJNOWE.js} +1 -1
- package/dist/ui/chunk-TNW2GNUR.js +1 -0
- package/dist/ui/{chunk-WFQU7V3W.js → chunk-UCYWQEAS.js} +1 -1
- package/dist/ui/{chunk-GT5EQSEX.js → chunk-UJX25CXD.js} +1 -1
- package/dist/ui/chunk-UPN3EMUS.js +1 -0
- package/dist/ui/{chunk-NJMNOITA.js → chunk-VPZHG7JL.js} +1 -1
- package/dist/ui/{chunk-BUNR5EU3.js → chunk-WASID5UU.js} +1 -1
- package/dist/ui/chunk-WC7KMPEQ.js +1 -0
- package/dist/ui/chunk-WRA24P66.js +7 -0
- package/dist/ui/{chunk-LROR6N3B.js.LEGAL.txt → chunk-WRA24P66.js.LEGAL.txt} +5 -1
- package/dist/ui/chunk-XACLTYBB.js +5 -0
- package/dist/ui/{chunk-VD6G5NV4.js → chunk-XOWWPE7X.js} +12 -12
- package/dist/ui/chunk-XUBZH4ON.js +1 -0
- package/dist/ui/{chunk-QF3GPZTI.js → chunk-Y5EOMMNI.js} +1 -1
- package/dist/ui/{chunk-NSOTG64N.js → chunk-YBHFGQ3Z.js} +1 -1
- package/dist/ui/chunk-YP6ZH3MT.js +1 -0
- package/dist/ui/{chunk-UUVAD4U4.js → chunk-Z3ZJJWFT.js} +1 -1
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-4G7S2LJH.js +0 -1411
- package/dist/chunk-AJDMNTZQ.js +0 -187
- package/dist/ui/AIPage-VOTAEVJE.js +0 -1
- package/dist/ui/AssetsPage-EWGRMRPJ.js +0 -1
- package/dist/ui/CollectionPage-N5JIAUDS.js +0 -1
- package/dist/ui/ComparePage-JDPVU2VA.js +0 -1
- package/dist/ui/DataPage-37D4CMLZ.js +0 -1
- package/dist/ui/DataSourcePage-LX5ASYQN.js +0 -1
- package/dist/ui/DocTranslationsPage-V5M4KB7X.js +0 -1
- package/dist/ui/DocumentPage-SURTQJPG.js +0 -1
- package/dist/ui/EditDataSourcePage-O7DOV5LX.js +0 -1
- package/dist/ui/EditReleasePage-NDYTKGXY.js +0 -1
- package/dist/ui/EmbeddedAIPage-RJOUIPF2.js +0 -1
- package/dist/ui/EmbeddedDocumentPage-SLEULNNI.js +0 -1
- package/dist/ui/LogsPage-ZGBP3I35.js +0 -1
- package/dist/ui/NewDataSourcePage-GQONTMP4.js +0 -1
- package/dist/ui/NewReleasePage-7ZKXHDTD.js +0 -1
- package/dist/ui/ProjectPage-F7W7X6YO.js +0 -1
- package/dist/ui/ReleasePage-ZKMNYPML.js +0 -1
- package/dist/ui/ReleasesPage-JHCE6AEJ.js +0 -1
- package/dist/ui/SettingsPage-MWCPZPGE.js +0 -1
- package/dist/ui/TaskPage-73NLAR4J.js +0 -1
- package/dist/ui/TasksPage-IKPW2OQO.js +0 -1
- package/dist/ui/TranslationsArbPage-QVN66DIW.js +0 -2
- package/dist/ui/TranslationsEditPage-ZOELF5PK.js +0 -1
- package/dist/ui/ai-tools-4DWMFQS6.js +0 -1
- package/dist/ui/chunk-2RAVKX2Z.js +0 -19
- package/dist/ui/chunk-344GZOGG.js +0 -84
- package/dist/ui/chunk-4ISFTE2G.js +0 -5
- package/dist/ui/chunk-BT2NTAW2.js +0 -1
- package/dist/ui/chunk-C2BLMTPR.js +0 -3
- package/dist/ui/chunk-D3UIZHRK.js +0 -1
- package/dist/ui/chunk-DS27MO63.js +0 -1
- package/dist/ui/chunk-HO3W4RVG.js +0 -1
- package/dist/ui/chunk-IOR72US3.js +0 -1
- package/dist/ui/chunk-KRNQ6L35.js +0 -1
- package/dist/ui/chunk-LROR6N3B.js +0 -7
- package/dist/ui/chunk-N3JSLTMV.js +0 -1
- package/dist/ui/chunk-PPYM4O5N.js +0 -1
- package/dist/ui/chunk-TOGLZDK3.js +0 -1
- package/dist/ui/chunk-TPJCPCRR.js +0 -1
- package/dist/ui/chunk-VPHBKJ3I.js +0 -1
- package/dist/ui/chunk-YUU6LWQK.js +0 -1
- package/dist/ui/chunk-Z6DBYLIM.js +0 -1
- /package/dist/ui/{ImageEditorDialog-GGS4VFEA.js.LEGAL.txt → ImageEditorDialog-YDKOGVJV.js.LEGAL.txt} +0 -0
- /package/dist/ui/{chunk-Y3MCFLQU.js.LEGAL.txt → chunk-7UHZS56B.js.LEGAL.txt} +0 -0
- /package/dist/ui/{chunk-NJMNOITA.js.LEGAL.txt → chunk-VPZHG7JL.js.LEGAL.txt} +0 -0
- /package/dist/ui/{chunk-VD6G5NV4.js.LEGAL.txt → chunk-XOWWPE7X.js.LEGAL.txt} +0 -0
package/dist/cli.js
CHANGED
package/dist/client.js
CHANGED
package/dist/core/ai-tools.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Built-in CMS tools exposed to the chat model on the `/cms/ai` page.
|
|
3
3
|
*
|
|
4
|
-
* Read tools (`doc_get`, `docs_list`, etc.) execute
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Read tools (`doc_get`, `docs_list`, etc.) run their `execute` against a
|
|
5
|
+
* pluggable `CmsToolReadBackend`. The `/cms/ai` chat now streams directly from
|
|
6
|
+
* the browser, so the client supplies a Firebase-web-SDK backend (see
|
|
7
|
+
* `ui/components/RootAIChat/clientCmsTools.ts`). The factory itself is
|
|
8
|
+
* data-source agnostic.
|
|
9
9
|
*
|
|
10
10
|
* Write tools (`doc_set`, `doc_create`, `doc_updateField`, `doc_duplicate`)
|
|
11
11
|
* stay schema-only here — the browser executes them via `onToolCall` so the
|
|
@@ -15,16 +15,12 @@
|
|
|
15
15
|
* Validation helpers (`validateFields`, `validateValueAtPath`) live here
|
|
16
16
|
* too so both browser and server can share the same checks.
|
|
17
17
|
*
|
|
18
|
-
* Browser-import safety: this module is
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* are referenced as types only; the actual instance is passed in at call
|
|
22
|
-
* time via `CmsToolContext`.
|
|
18
|
+
* Browser-import safety: this module is imported by the browser bundle, so it
|
|
19
|
+
* must not pull server-only modules (`firebase-admin`, `node:*`) into runtime
|
|
20
|
+
* imports. The backend implementation is injected at call time.
|
|
23
21
|
*/
|
|
24
|
-
import type { RootConfig } from '@blinkk/root';
|
|
25
22
|
import { ToolSet } from 'ai';
|
|
26
|
-
import
|
|
27
|
-
import { Collection } from './schema.js';
|
|
23
|
+
import { Collection, Field } from './schema.js';
|
|
28
24
|
import { validateFields } from './validation.js';
|
|
29
25
|
/** Tool ids handled client-side. Kept in sync with the schemas below. */
|
|
30
26
|
export declare const CMS_TOOL_NAMES: readonly ["collections_list", "docs_list", "doc_get", "doc_getVersion", "doc_set", "doc_create", "doc_updateField", "doc_edit", "doc_duplicate", "doc_listVersions", "doc_translateField", "schema_get"];
|
|
@@ -35,48 +31,83 @@ export type CmsToolName = (typeof CMS_TOOL_NAMES)[number];
|
|
|
35
31
|
* and the model must not write to Firestore directly.
|
|
36
32
|
*/
|
|
37
33
|
export declare const READ_ONLY_CMS_TOOL_NAMES: readonly CmsToolName[];
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
34
|
+
/** A CMS document shaped for the model (fields/sys already unmarshalled). */
|
|
35
|
+
export interface CmsToolDoc {
|
|
36
|
+
id: string;
|
|
37
|
+
collection: string;
|
|
38
|
+
slug: string;
|
|
39
|
+
sys: Record<string, unknown>;
|
|
40
|
+
fields: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/** Lightweight doc summary returned by `docs_list`. */
|
|
43
|
+
export interface CmsToolDocSummary {
|
|
44
|
+
id: string;
|
|
45
|
+
slug: string;
|
|
46
|
+
sys: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
/** Version summary returned by `doc_listVersions`. */
|
|
49
|
+
export interface CmsToolVersionSummary {
|
|
50
|
+
versionId: string;
|
|
51
|
+
sys: Record<string, unknown>;
|
|
52
|
+
tags: string[];
|
|
53
|
+
publishMessage?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Collection summary returned by `collections_list`. */
|
|
56
|
+
export interface CmsToolCollectionSummary {
|
|
57
|
+
id: string;
|
|
58
|
+
name?: string;
|
|
59
|
+
description?: string;
|
|
47
60
|
}
|
|
48
61
|
/**
|
|
49
|
-
*
|
|
50
|
-
* the
|
|
51
|
-
*
|
|
62
|
+
* Data-source backing the read tools. Implemented server-side (Firebase Admin)
|
|
63
|
+
* or in the browser (Firebase web SDK — see `clientCmsTools.ts`). The factory
|
|
64
|
+
* is agnostic to where the reads run.
|
|
65
|
+
*
|
|
66
|
+
* Implementations own docId parsing and unmarshalling so the tool `execute`
|
|
67
|
+
* blocks stay thin and the returned shapes are model-ready.
|
|
52
68
|
*/
|
|
53
|
-
export interface
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
69
|
+
export interface CmsToolReadBackend {
|
|
70
|
+
/** Lists all collections with optional name/description metadata. */
|
|
71
|
+
listCollections(): Promise<CmsToolCollectionSummary[]>;
|
|
72
|
+
/** Lists docs in a collection (draft or published). */
|
|
73
|
+
listDocs(collectionId: string, options: {
|
|
74
|
+
mode: 'draft' | 'published';
|
|
75
|
+
limit: number;
|
|
76
|
+
}): Promise<CmsToolDocSummary[]>;
|
|
77
|
+
/** Reads a single doc, or `null` if it does not exist. */
|
|
78
|
+
getDoc(docId: string, options: {
|
|
79
|
+
mode: 'draft' | 'published';
|
|
80
|
+
}): Promise<CmsToolDoc | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Reads a specific version of a doc. `versionId` is "draft", "published" or
|
|
83
|
+
* a numeric timestamp. Returns `null` if it does not exist.
|
|
84
|
+
*/
|
|
85
|
+
getDocVersion(docId: string, versionId: string): Promise<CmsToolDoc | null>;
|
|
86
|
+
/** Lists a doc's version history, most recent first. */
|
|
87
|
+
listVersions(docId: string, options: {
|
|
60
88
|
limit: number;
|
|
61
|
-
})
|
|
89
|
+
}): Promise<CmsToolVersionSummary[]>;
|
|
90
|
+
/**
|
|
91
|
+
* Returns the simplified field definitions for a collection (see
|
|
92
|
+
* `simplifyFields`), or `null` if the collection is unknown.
|
|
93
|
+
*/
|
|
94
|
+
getSchemaFields(collectionId: string): Promise<unknown[] | null>;
|
|
62
95
|
}
|
|
63
96
|
/**
|
|
64
97
|
* Returns a `ToolSet` filtered to only the read-only CMS tools. Use this in
|
|
65
98
|
* flows where the AI assists with proposing changes that the user reviews
|
|
66
99
|
* and saves manually (so the model can read context but cannot mutate data).
|
|
67
100
|
*/
|
|
68
|
-
export declare function createReadOnlyCmsTools(
|
|
101
|
+
export declare function createReadOnlyCmsTools(backend: CmsToolReadBackend): ToolSet;
|
|
69
102
|
/**
|
|
70
103
|
* Builds the full tool set advertised to the model.
|
|
71
104
|
*
|
|
72
105
|
* Read tools (`collections_list`, `docs_list`, `docs_search`, `doc_get`,
|
|
73
|
-
* `doc_getVersion`, `doc_listVersions`, `schema_get`) carry
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* browser
|
|
77
|
-
*
|
|
78
|
-
* executes them via `onToolCall` so the user can approve diffs before
|
|
79
|
-
* persistence.
|
|
106
|
+
* `doc_getVersion`, `doc_listVersions`, `schema_get`) carry an `execute` that
|
|
107
|
+
* delegates to the supplied `CmsToolReadBackend`. Write tools (`doc_set`,
|
|
108
|
+
* `doc_create`, `doc_updateField`, `doc_duplicate`, `doc_translateField`)
|
|
109
|
+
* remain schema-only — the browser executes them via `onToolCall` so the user
|
|
110
|
+
* can approve diffs before persistence.
|
|
80
111
|
*
|
|
81
112
|
* Safety policy: this tool set is intentionally read + draft-write only.
|
|
82
113
|
* The following operations are deliberately NOT exposed to the model
|
|
@@ -97,7 +128,16 @@ export declare function createReadOnlyCmsTools(ctx: CmsToolContext): ToolSet;
|
|
|
97
128
|
* If you add new write tools here, keep them limited to draft-mode edits
|
|
98
129
|
* the user can easily review before publishing.
|
|
99
130
|
*/
|
|
100
|
-
export declare function createCmsTools(
|
|
131
|
+
export declare function createCmsTools(backend: CmsToolReadBackend): ToolSet;
|
|
132
|
+
/**
|
|
133
|
+
* Reduces a collection's field definitions down to the bits the model needs
|
|
134
|
+
* (id, type, label, options, nested shape). Drops Root-internal metadata
|
|
135
|
+
* (preview, conditional visibility, default UI widget hints, etc.) since
|
|
136
|
+
* those would bloat the model context without adding decision-useful info.
|
|
137
|
+
*
|
|
138
|
+
* Exported so the browser backend can shape `schema_get` results the same way.
|
|
139
|
+
*/
|
|
140
|
+
export declare function simplifyFields(fields: Field[]): unknown[];
|
|
101
141
|
/**
|
|
102
142
|
* Validates `value` against the field schema located at `path` within
|
|
103
143
|
* `collection`. Returns validation errors if the field can be resolved and
|
package/dist/core/ai.d.ts
CHANGED
|
@@ -1,98 +1,26 @@
|
|
|
1
1
|
import { RootConfig } from '@blinkk/root';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { AiConfig, AiExecutionMode, AiModelConfig, resolveLanguageModel } from '../shared/ai/models.js';
|
|
3
|
+
import { deriveChatTitle } from '../shared/ai/prompt-utils.js';
|
|
4
|
+
export type { AiConfig, AiExecutionMode, AiModelCapabilities, AiModelConfig, AiProvider, } from '../shared/ai/models.js';
|
|
5
|
+
export { normalizeExecutionMode, resolveImageModel, resolveLanguageModel, withBrowserHeaders, } from '../shared/ai/models.js';
|
|
6
|
+
export { buildTitlePrompt, buildTitlePromptContext, deriveChatTitle, extractJsonFromResponse, mergeIncomingMessage, sanitizeDanglingToolCalls, sanitizeGeneratedTitle, stripUndefined, TITLE_GENERATION_SYSTEM_PROMPT, } from '../shared/ai/prompt-utils.js';
|
|
6
7
|
/** Filename of the project-level instructions file loaded into the AI prompt. */
|
|
7
8
|
export declare const ROOT_MD_FILENAME = "ROOT.md";
|
|
8
|
-
|
|
9
|
+
/** Default base system prompt for the Root AI chat. */
|
|
10
|
+
export declare const DEFAULT_CHAT_SYSTEM_PROMPT: string;
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
11
|
-
* endpoint
|
|
12
|
+
* Strips secrets from `AiConfig` before sending to the browser. Used by the
|
|
13
|
+
* `/cms/api/ai.config` endpoint and the inlined `window.__ROOT_CTX.ai` to
|
|
14
|
+
* populate the model picker. The key-bearing connection config is sent
|
|
15
|
+
* separately (and only for the selected model) via `serializeAiClientModel`.
|
|
12
16
|
*/
|
|
13
|
-
export type AiProvider = 'openai' | 'openai-compatible' | 'anthropic' | 'google';
|
|
14
|
-
/**
|
|
15
|
-
* Configuration for a single chat model.
|
|
16
|
-
*
|
|
17
|
-
* Inspired by Ollama's `Modelfile` and LiteLLM's model config: each entry maps
|
|
18
|
-
* a CMS-facing id to a provider, model id and credentials.
|
|
19
|
-
*/
|
|
20
|
-
export interface AiModelConfig {
|
|
21
|
-
/** Stable id used by the CMS UI and stored alongside chat history. */
|
|
22
|
-
id: string;
|
|
23
|
-
/** Optional human-readable label rendered in the model picker. */
|
|
24
|
-
label?: string;
|
|
25
|
-
/** Optional description shown under the label. */
|
|
26
|
-
description?: string;
|
|
27
|
-
/** AI provider/family to route requests to. */
|
|
28
|
-
provider: AiProvider;
|
|
29
|
-
/**
|
|
30
|
-
* Provider-specific model id (e.g. `gpt-4o`, `claude-opus-4-5`,
|
|
31
|
-
* `gemini-2.5-pro`). Defaults to `id` if omitted.
|
|
32
|
-
*/
|
|
33
|
-
modelId?: string;
|
|
34
|
-
/** API key for the provider. */
|
|
35
|
-
apiKey?: string;
|
|
36
|
-
/** Override the provider's base URL (required for `openai-compatible`). */
|
|
37
|
-
baseURL?: string;
|
|
38
|
-
/** Custom headers to send with each request. */
|
|
39
|
-
headers?: Record<string, string>;
|
|
40
|
-
/** Capabilities advertised to the UI. */
|
|
41
|
-
capabilities?: {
|
|
42
|
-
/** Whether the model can call tools. Defaults to `true`. */
|
|
43
|
-
tools?: boolean;
|
|
44
|
-
/** Whether the model can stream reasoning/thinking. Defaults to `false`. */
|
|
45
|
-
reasoning?: boolean;
|
|
46
|
-
/** Whether the model accepts image attachments. Defaults to `false`. */
|
|
47
|
-
attachments?: boolean;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Full AI config registered on the cms plugin.
|
|
52
|
-
*/
|
|
53
|
-
export interface AiConfig {
|
|
54
|
-
/** Models exposed in the model picker. The first entry is the default. */
|
|
55
|
-
models: AiModelConfig[];
|
|
56
|
-
/** Id of the default model. Defaults to the first model in `models`. */
|
|
57
|
-
defaultModel?: string;
|
|
58
|
-
/**
|
|
59
|
-
* Image generation models. Used by the image generator and any other
|
|
60
|
-
* features that produce images. Only the `openai` and `google` providers
|
|
61
|
-
* support image generation.
|
|
62
|
-
*/
|
|
63
|
-
imageModels?: AiModelConfig[];
|
|
64
|
-
/** Id of the default image model. Defaults to the first entry in `imageModels`. */
|
|
65
|
-
defaultImageModel?: string;
|
|
66
|
-
/**
|
|
67
|
-
* Optional system prompt prepended to every conversation. If a `ROOT.md`
|
|
68
|
-
* file exists at the project root, its contents are appended to this
|
|
69
|
-
* prompt automatically.
|
|
70
|
-
*/
|
|
71
|
-
systemPrompt?: string;
|
|
72
|
-
/** Maximum tool-loop steps before stopping. Defaults to 10. */
|
|
73
|
-
maxSteps?: number;
|
|
74
|
-
}
|
|
75
|
-
interface ChatRecord {
|
|
76
|
-
id: string;
|
|
77
|
-
createdBy: string;
|
|
78
|
-
createdAt: Timestamp;
|
|
79
|
-
modifiedAt: Timestamp;
|
|
80
|
-
modelId?: string;
|
|
81
|
-
title?: string;
|
|
82
|
-
messages: UIMessage[];
|
|
83
|
-
}
|
|
84
|
-
/** Resolves an `AiModelConfig` to an AI SDK `LanguageModel` instance. */
|
|
85
|
-
export declare function resolveLanguageModel(model: AiModelConfig): LanguageModel;
|
|
86
|
-
/** Resolves an `AiModelConfig` to an AI SDK `ImageModel` instance. */
|
|
87
|
-
export declare function resolveImageModel(model: AiModelConfig): ImageModel;
|
|
88
|
-
/** Strips secrets from `AiConfig` before sending to the browser. */
|
|
89
17
|
export declare function serializeAiConfig(config: AiConfig): {
|
|
90
18
|
defaultModel: string;
|
|
91
19
|
models: {
|
|
92
20
|
id: string;
|
|
93
21
|
label: string;
|
|
94
22
|
description: string | undefined;
|
|
95
|
-
provider: AiProvider;
|
|
23
|
+
provider: import("../shared/ai/models.js").AiProvider;
|
|
96
24
|
capabilities: {
|
|
97
25
|
tools: boolean;
|
|
98
26
|
reasoning: boolean;
|
|
@@ -101,61 +29,37 @@ export declare function serializeAiConfig(config: AiConfig): {
|
|
|
101
29
|
}[];
|
|
102
30
|
imageGenerationEnabled: boolean;
|
|
103
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Serializes a single chat model's full connection config — INCLUDING the API
|
|
34
|
+
* key, base URL and custom headers — for direct browser-to-provider calls.
|
|
35
|
+
*
|
|
36
|
+
* Security note: this intentionally exposes the provider API key to the
|
|
37
|
+
* authenticated CMS client (the project opted into direct client-side calls).
|
|
38
|
+
* Only return it from authenticated endpoints, and only for the model the user
|
|
39
|
+
* actually selected.
|
|
40
|
+
*/
|
|
41
|
+
export declare function serializeAiClientModel(model: AiModelConfig): {
|
|
42
|
+
id: string;
|
|
43
|
+
label: string;
|
|
44
|
+
description: string | undefined;
|
|
45
|
+
provider: import("../shared/ai/models.js").AiProvider;
|
|
46
|
+
modelId: string;
|
|
47
|
+
apiKey: string | undefined;
|
|
48
|
+
baseURL: string | undefined;
|
|
49
|
+
headers: Record<string, string> | undefined;
|
|
50
|
+
capabilities: {
|
|
51
|
+
tools: boolean;
|
|
52
|
+
reasoning: boolean;
|
|
53
|
+
attachments: boolean;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export type SerializedAiClientModel = ReturnType<typeof serializeAiClientModel>;
|
|
104
57
|
/** Returns the AI config registered on the CMS plugin, or `null`. */
|
|
105
58
|
export declare function getAiConfig(rootConfig: RootConfig): AiConfig | null;
|
|
106
59
|
/** Returns the model config matching `modelId`, or the default model. */
|
|
107
60
|
export declare function findModel(config: AiConfig, modelId?: string): AiModelConfig | null;
|
|
108
61
|
/** Returns the image model config matching `modelId`, or the default image model. */
|
|
109
62
|
export declare function findImageModel(config: AiConfig, modelId?: string): AiModelConfig | null;
|
|
110
|
-
export declare function normalizeExecutionMode(value: unknown): AiExecutionMode;
|
|
111
|
-
/**
|
|
112
|
-
* Persists chat sessions to Firestore so that users can resume past
|
|
113
|
-
* conversations from the chat history sidebar.
|
|
114
|
-
*/
|
|
115
|
-
export declare class ChatStore {
|
|
116
|
-
cmsClient: RootCMSClient;
|
|
117
|
-
user: string;
|
|
118
|
-
constructor(cmsClient: RootCMSClient, user: string);
|
|
119
|
-
collection(): FirebaseFirestore.CollectionReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
|
|
120
|
-
createChat(options?: {
|
|
121
|
-
id?: string;
|
|
122
|
-
modelId?: string;
|
|
123
|
-
}): Promise<ChatRecord>;
|
|
124
|
-
getChat(id: string): Promise<ChatRecord | null>;
|
|
125
|
-
listChats(options?: {
|
|
126
|
-
limit?: number;
|
|
127
|
-
}): Promise<ChatRecord[]>;
|
|
128
|
-
deleteChat(id: string): Promise<void>;
|
|
129
|
-
updateMessages(id: string, messages: UIMessage[], options?: {
|
|
130
|
-
modelId?: string;
|
|
131
|
-
title?: string;
|
|
132
|
-
}): Promise<void>;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Merges the latest incoming message into the persisted chat history.
|
|
136
|
-
*
|
|
137
|
-
* The client posts only the last message; the server holds the rest in
|
|
138
|
-
* Firestore. After client-side tool execution the SDK resubmits the *same*
|
|
139
|
-
* assistant message — now carrying tool results — under the id it was
|
|
140
|
-
* streamed with. That id already exists in the persisted history (saved by
|
|
141
|
-
* `onFinish` before the results came back), so a naive append would
|
|
142
|
-
* duplicate it: the stored copy still has unresolved tool calls, which
|
|
143
|
-
* convert to `tool_use` blocks with no following `tool_result` and the model
|
|
144
|
-
* provider rejects the request.
|
|
145
|
-
*
|
|
146
|
-
* Replacing the matched entry (and dropping anything after it) keeps message
|
|
147
|
-
* ids unique and the tool-call/result pairing intact. A genuinely new
|
|
148
|
-
* message id is appended as usual.
|
|
149
|
-
*/
|
|
150
|
-
export declare function mergeIncomingMessage(stored: UIMessage[], incoming: UIMessage): UIMessage[];
|
|
151
|
-
/**
|
|
152
|
-
* Synthesizes an aborted result for any tool-call part still awaiting one, so
|
|
153
|
-
* every `tool_use` keeps a matching `tool_result` when the history is handed
|
|
154
|
-
* to the model. Left unresolved, such parts (from an abandoned turn) make the
|
|
155
|
-
* provider reject the next request. Returns the original array unchanged when
|
|
156
|
-
* there is nothing to repair.
|
|
157
|
-
*/
|
|
158
|
-
export declare function sanitizeDanglingToolCalls(messages: UIMessage[]): UIMessage[];
|
|
159
63
|
/**
|
|
160
64
|
* Reads the project's `ROOT.md` file, if present. Mirrors the convention used
|
|
161
65
|
* by tools like `AGENTS.md` and `CLAUDE.md`: developers can drop a markdown
|
|
@@ -173,106 +77,44 @@ export declare function readRootMd(rootDir: string): Promise<string | null>;
|
|
|
173
77
|
* distinguish it from the framework-provided instructions.
|
|
174
78
|
*/
|
|
175
79
|
export declare function buildSystemPrompt(basePrompt: string, rootMd: string | null): string;
|
|
176
|
-
/** Derives a short title from the first user message (used as fallback). */
|
|
177
|
-
export declare function deriveChatTitle(messages: UIMessage[]): string;
|
|
178
|
-
/**
|
|
179
|
-
* Extracts the first user turn and first assistant text turn as a plain-text
|
|
180
|
-
* transcript, suitable for the title-generation prompt. Skips tool-call
|
|
181
|
-
* parts, reasoning chunks, and attachments so the model sees the
|
|
182
|
-
* conversational substance and nothing else.
|
|
183
|
-
*
|
|
184
|
-
* Only the opening exchange is included on purpose — the chat title should
|
|
185
|
-
* describe what the conversation is *about*, anchored on the user's initial
|
|
186
|
-
* ask, not drift as later follow-ups arrive.
|
|
187
|
-
*/
|
|
188
|
-
export declare function buildTitlePromptContext(messages: UIMessage[]): string;
|
|
189
|
-
/**
|
|
190
|
-
* Strips the cruft LLMs commonly emit around a title — leading "Title:"
|
|
191
|
-
* preamble, surrounding quotes, trailing punctuation, internal newlines —
|
|
192
|
-
* and enforces a hard length cap.
|
|
193
|
-
*/
|
|
194
|
-
export declare function sanitizeGeneratedTitle(raw: string): string;
|
|
195
80
|
/**
|
|
196
|
-
* Uses the AI model to generate a short summary title for
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* than echoing the first line verbatim.
|
|
81
|
+
* Uses the AI model to generate a short summary title for a chat. Kept for
|
|
82
|
+
* server-side callers; the browser chat generates titles client-side using the
|
|
83
|
+
* shared `TITLE_GENERATION_SYSTEM_PROMPT` + `buildTitlePrompt` helpers.
|
|
200
84
|
*
|
|
201
85
|
* Falls back to `deriveChatTitle` if the generation fails or returns an
|
|
202
86
|
* empty result.
|
|
203
87
|
*/
|
|
204
|
-
export declare function generateChatTitle(model:
|
|
205
|
-
export
|
|
88
|
+
export declare function generateChatTitle(model: ReturnType<typeof resolveLanguageModel>, messages: Parameters<typeof deriveChatTitle>[0]): Promise<string>;
|
|
89
|
+
export declare function buildExecutionModePrompt(mode: AiExecutionMode): string;
|
|
90
|
+
export interface BuildChatSystemPromptOptions {
|
|
206
91
|
rootConfig: RootConfig;
|
|
207
|
-
cmsClient: RootCMSClient;
|
|
208
92
|
config: AiConfig;
|
|
209
|
-
|
|
210
|
-
messages: UIMessage[];
|
|
211
|
-
chatId: string;
|
|
212
|
-
user: string;
|
|
213
|
-
executionMode?: AiExecutionMode;
|
|
214
|
-
/**
|
|
215
|
-
* Title already saved on this chat. When non-empty the server will NOT
|
|
216
|
-
* regenerate it on this turn — titles are derived once, on the first
|
|
217
|
-
* assistant response, so they describe the original ask instead of
|
|
218
|
-
* thrashing as follow-up messages arrive.
|
|
219
|
-
*/
|
|
220
|
-
existingTitle?: string;
|
|
93
|
+
executionMode: AiExecutionMode;
|
|
221
94
|
/**
|
|
222
95
|
* When set, tells the model which document the user is currently viewing
|
|
223
96
|
* in the CMS UI so phrases like "this document" can be resolved.
|
|
224
97
|
*/
|
|
225
98
|
activeDocId?: string;
|
|
226
|
-
/**
|
|
227
|
-
* Loads a single collection's schema. The caller owns dev-vs-prod schema
|
|
228
|
-
* resolution (Vite SSR vs. prebuilt `dist/collections/*.json`).
|
|
229
|
-
*/
|
|
230
|
-
loadCollection: (collectionId: string) => Promise<Collection | null>;
|
|
231
|
-
/** Loads every project collection keyed by id. */
|
|
232
|
-
loadAllCollections: () => Promise<Record<string, Collection>>;
|
|
233
99
|
}
|
|
234
|
-
export declare function buildExecutionModePrompt(mode: AiExecutionMode): string;
|
|
235
100
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
101
|
+
* Assembles the chat system prompt: base prompt + workspace context + tool
|
|
102
|
+
* safety policy + execution-mode workflow + (optional) active-doc context,
|
|
103
|
+
* with `ROOT.md` appended when present.
|
|
239
104
|
*/
|
|
240
|
-
export declare function
|
|
241
|
-
export interface
|
|
105
|
+
export declare function buildChatSystemPrompt(options: BuildChatSystemPromptOptions): Promise<string>;
|
|
106
|
+
export interface BuildEditSystemPromptOptions {
|
|
242
107
|
rootConfig: RootConfig;
|
|
243
|
-
cmsClient: RootCMSClient;
|
|
244
|
-
user: string;
|
|
245
|
-
config: AiConfig;
|
|
246
|
-
model: AiModelConfig;
|
|
247
|
-
messages: UIMessage[];
|
|
248
108
|
/** The JSON object the user is editing. Injected as context for the model. */
|
|
249
109
|
editData: unknown;
|
|
250
|
-
loadCollection: (collectionId: string) => Promise<Collection | null>;
|
|
251
|
-
loadAllCollections: () => Promise<Record<string, Collection>>;
|
|
252
110
|
}
|
|
253
111
|
/**
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
* - Uses an edit-specific system prompt that injects the JSON the user is
|
|
259
|
-
* editing and the project's `root-cms.d.ts` types, and instructs the model
|
|
260
|
-
* to end every response with a fenced ```json block containing the
|
|
261
|
-
* complete proposed new JSON. The client extracts that block to populate
|
|
262
|
-
* the diff viewer.
|
|
263
|
-
* - Tools are filtered to read-only (see `createReadOnlyCmsTools`). The user
|
|
264
|
-
* approves changes via the modal's "Save" button, so the model must not
|
|
265
|
-
* mutate Firestore directly.
|
|
266
|
-
* - No Firestore persistence — edit sessions are ephemeral and don't show up
|
|
267
|
-
* in the user's chat history.
|
|
268
|
-
*/
|
|
269
|
-
export declare function runEditObjectStream(options: RunEditObjectStreamOptions): Promise<Response>;
|
|
270
|
-
/**
|
|
271
|
-
* Recursively removes `undefined` values from an object/array. Returns a new
|
|
272
|
-
* structure; the input is not mutated. Used to clean payloads before sending
|
|
273
|
-
* them to Firestore, which rejects `undefined` outright.
|
|
112
|
+
* Assembles the system prompt for the array-item "Edit with AI" diff-viewer
|
|
113
|
+
* flow: the edit instructions + output-format contract + read-only tool policy
|
|
114
|
+
* + the project's `root-cms.d.ts` types + the JSON being edited (wrapped as
|
|
115
|
+
* untrusted data), with `ROOT.md` appended when present.
|
|
274
116
|
*/
|
|
275
|
-
export declare function
|
|
117
|
+
export declare function buildEditSystemPrompt(options: BuildEditSystemPromptOptions): Promise<string>;
|
|
276
118
|
export interface SummarizeDiffOptions {
|
|
277
119
|
before: Record<string, any> | null;
|
|
278
120
|
after: Record<string, any> | null;
|
|
@@ -322,9 +164,3 @@ export interface GenerateImageResult {
|
|
|
322
164
|
* to storage.
|
|
323
165
|
*/
|
|
324
166
|
export declare function generateImage(rootConfig: RootConfig, options: GenerateImageOptions): Promise<GenerateImageResult>;
|
|
325
|
-
/**
|
|
326
|
-
* Extracts JSON from an AI response that may contain markdown code blocks.
|
|
327
|
-
* @internal
|
|
328
|
-
*/
|
|
329
|
-
export declare function extractJsonFromResponse(responseText: string): string;
|
|
330
|
-
export {};
|
package/dist/core/plugin.d.ts
CHANGED
|
@@ -182,11 +182,17 @@ export type CMSPluginOptions = {
|
|
|
182
182
|
onAction?: (action: Action) => any;
|
|
183
183
|
/**
|
|
184
184
|
* Configures the Root CMS AI chat (`/cms/ai`). Provide one or more models
|
|
185
|
-
* —
|
|
185
|
+
* — each entry declares the provider, model id and credentials. The shape
|
|
186
|
+
* mirrors open source tools like Ollama and LiteLLM.
|
|
186
187
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
188
|
+
* IMPORTANT: the streaming chat (`/cms/ai`, the document-editor AI panel and
|
|
189
|
+
* the "Edit with AI" modal) calls the provider DIRECTLY from the browser —
|
|
190
|
+
* SSE proxying through the server did not work on App Engine / Firebase
|
|
191
|
+
* Hosting. The selected model's API key is therefore delivered to the
|
|
192
|
+
* authenticated CMS client. Use keys scoped/billed for this trusted,
|
|
193
|
+
* signed-in audience. The one-shot helpers (diff summaries, publish
|
|
194
|
+
* messages, translations, alt text, image generation) still run server-side,
|
|
195
|
+
* so their keys stay on the server.
|
|
190
196
|
*
|
|
191
197
|
* Example:
|
|
192
198
|
* ```ts
|
package/dist/core/schema.d.ts
CHANGED
|
@@ -17,6 +17,64 @@ export interface CommonFieldProps {
|
|
|
17
17
|
/** Hides just the field label in the CMS UI. */
|
|
18
18
|
hideLabel?: boolean;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Sources the selectable values for a field from a field within another CMS
|
|
22
|
+
* document.
|
|
23
|
+
*
|
|
24
|
+
* Use this when a set of allowed values is managed centrally in the CMS (e.g. a
|
|
25
|
+
* list of feature flags defined in a global module) and you want other fields
|
|
26
|
+
* to pick from that list instead of typing free-form strings.
|
|
27
|
+
*
|
|
28
|
+
* Example: source a `flag` select's options from the `name` of each item in
|
|
29
|
+
* the `flags` array of the `GlobalModules/flags` document.
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* schema.select({
|
|
33
|
+
* id: 'flag',
|
|
34
|
+
* source: {
|
|
35
|
+
* doc: 'GlobalModules/flags',
|
|
36
|
+
* field: 'flags',
|
|
37
|
+
* valueKey: 'name',
|
|
38
|
+
* helpKey: 'description',
|
|
39
|
+
* },
|
|
40
|
+
* creatable: true,
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export interface DocumentSource {
|
|
45
|
+
/**
|
|
46
|
+
* The document to source values from, in `<collection>/<slug>` format, e.g.
|
|
47
|
+
* `GlobalModules/flags`.
|
|
48
|
+
*/
|
|
49
|
+
doc: string;
|
|
50
|
+
/**
|
|
51
|
+
* The field within the document that holds the values, e.g. `flags`. This is
|
|
52
|
+
* usually an array; for an array of objects use `valueKey`/`labelKey` to map
|
|
53
|
+
* each item, and for an array of strings each string is used directly.
|
|
54
|
+
*/
|
|
55
|
+
field: string;
|
|
56
|
+
/**
|
|
57
|
+
* The key on each item to use as the stored value, e.g. `name`. Dot-paths are
|
|
58
|
+
* supported for nested keys (e.g. `meta.id`). Omit for arrays of strings.
|
|
59
|
+
*/
|
|
60
|
+
valueKey?: string;
|
|
61
|
+
/**
|
|
62
|
+
* The key on each item to use as the display label, e.g. `name`. Dot-paths
|
|
63
|
+
* are supported. Defaults to `valueKey`.
|
|
64
|
+
*/
|
|
65
|
+
labelKey?: string;
|
|
66
|
+
/**
|
|
67
|
+
* The key on each item to use as secondary help text, shown in a smaller,
|
|
68
|
+
* dimmed line beneath the label in the dropdown, e.g. `description`. Dot-paths
|
|
69
|
+
* are supported.
|
|
70
|
+
*/
|
|
71
|
+
helpKey?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The source of selectable values for a field. Currently only a CMS document
|
|
75
|
+
* source is supported; other source types may be added in the future.
|
|
76
|
+
*/
|
|
77
|
+
export type FieldValueSource = DocumentSource;
|
|
20
78
|
export type StringField = CommonFieldProps & {
|
|
21
79
|
type: 'string';
|
|
22
80
|
default?: string;
|
|
@@ -67,19 +125,27 @@ export declare function boolean(field: Omit<BooleanField, 'type'>): BooleanField
|
|
|
67
125
|
export type SelectField = CommonFieldProps & {
|
|
68
126
|
type: 'select';
|
|
69
127
|
default?: string;
|
|
128
|
+
/** A static list of options to choose from. */
|
|
70
129
|
options?: Array<{
|
|
71
130
|
value: string;
|
|
72
131
|
label?: string;
|
|
73
132
|
}> | string[];
|
|
133
|
+
/**
|
|
134
|
+
* Dynamically source the options from a field in another CMS document,
|
|
135
|
+
* instead of the static `options` list. See {@link DocumentSource}.
|
|
136
|
+
*/
|
|
137
|
+
source?: FieldValueSource;
|
|
138
|
+
/**
|
|
139
|
+
* Whether to allow the user to enter arbitrary values that aren't in the
|
|
140
|
+
* options/source list. Defaults to `false`.
|
|
141
|
+
*/
|
|
142
|
+
creatable?: boolean;
|
|
74
143
|
translate?: boolean;
|
|
75
144
|
searchable?: boolean;
|
|
76
145
|
};
|
|
77
146
|
export declare function select(field: Omit<SelectField, 'type'>): SelectField;
|
|
78
147
|
export type MultiSelectField = Omit<SelectField, 'type'> & {
|
|
79
148
|
type: 'multiselect';
|
|
80
|
-
/** Set to `true` to allow users to create arbitrary values. */
|
|
81
|
-
creatable?: boolean;
|
|
82
|
-
translate?: boolean;
|
|
83
149
|
};
|
|
84
150
|
export declare function multiselect(field: Omit<MultiSelectField, 'type'>): MultiSelectField;
|
|
85
151
|
export type ImageField = CommonFieldProps & {
|
|
@@ -416,6 +482,25 @@ export type Collection = SchemaWithTypes & {
|
|
|
416
482
|
/** Sort direction. Defaults to ascending. */
|
|
417
483
|
direction?: 'asc' | 'desc';
|
|
418
484
|
}>;
|
|
485
|
+
/**
|
|
486
|
+
* Options that control how the document listing for this collection is
|
|
487
|
+
* rendered in the CMS.
|
|
488
|
+
*/
|
|
489
|
+
viewOptions?: {
|
|
490
|
+
/**
|
|
491
|
+
* Forces the document listing to always use the "compact" view, which
|
|
492
|
+
* renders a condensed table (image, doc id, title, badges, and
|
|
493
|
+
* created/modified timestamps) instead of the default cards with large
|
|
494
|
+
* titles and preview URLs. Useful for collections that don't have
|
|
495
|
+
* meaningful preview metadata (e.g. redirects).
|
|
496
|
+
*
|
|
497
|
+
* When set, the listing is locked to the compact layout and the CMS
|
|
498
|
+
* "View" density control is disabled. When unset, users can choose the
|
|
499
|
+
* listing density (their choice is remembered globally and stays sticky as
|
|
500
|
+
* they navigate between collections).
|
|
501
|
+
*/
|
|
502
|
+
compact?: boolean;
|
|
503
|
+
};
|
|
419
504
|
};
|
|
420
505
|
export declare function defineCollection(collection: Omit<Collection, 'id'>): Omit<Collection, 'id'>;
|
|
421
506
|
export declare const collection: typeof defineCollection;
|