@proteos/sdk 0.54.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-KMNEQP3G.cjs → chunk-3UBIL3WV.cjs} +38 -3
- package/dist/chunk-3UBIL3WV.cjs.map +1 -0
- package/dist/{chunk-OS4IQ5VH.js → chunk-WJYUQBEG.js} +35 -4
- package/dist/chunk-WJYUQBEG.js.map +1 -0
- package/dist/index.cjs +139 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +251 -39
- package/dist/index.d.ts +251 -39
- package/dist/index.js +24 -2
- package/dist/index.js.map +1 -1
- package/dist/meta/index.cjs +91 -75
- package/dist/meta/index.d.cts +1 -1
- package/dist/meta/index.d.ts +1 -1
- package/dist/meta/index.js +1 -1
- package/dist/{types-amvSTwJy.d.cts → types-CylP2A4p.d.cts} +48 -7
- package/dist/{types-amvSTwJy.d.ts → types-CylP2A4p.d.ts} +48 -7
- package/package.json +1 -1
- package/src/agent/index.ts +42 -6
- package/src/agent/model-types.ts +193 -0
- package/src/agent/models.ts +67 -0
- package/src/index.ts +20 -1
- package/src/meta/index.ts +6 -0
- package/src/meta/layout/elements.ts +2 -2
- package/src/meta/record-title.ts +50 -0
- package/src/meta/types.ts +25 -5
- package/src/workflow/types.ts +3 -1
- package/dist/chunk-KMNEQP3G.cjs.map +0 -1
- package/dist/chunk-OS4IQ5VH.js.map +0 -1
|
@@ -1850,7 +1850,7 @@ type SchedulingPickerElement = CommonProps & {
|
|
|
1850
1850
|
contact_id?: string;
|
|
1851
1851
|
is_header_hidden?: boolean;
|
|
1852
1852
|
};
|
|
1853
|
-
type TextVariant = 'heading' | 'subheading' | 'body' | 'caption' | 'callout';
|
|
1853
|
+
type TextVariant = 'heading' | 'subheading' | 'body' | 'caption' | 'callout' | 'block-title';
|
|
1854
1854
|
type TextElement = CommonProps & {
|
|
1855
1855
|
type: 'text';
|
|
1856
1856
|
variant: TextVariant;
|
|
@@ -1997,6 +1997,28 @@ declare const PageLayoutSchema: z.ZodObject<{
|
|
|
1997
1997
|
} | undefined;
|
|
1998
1998
|
}>;
|
|
1999
1999
|
|
|
2000
|
+
/**
|
|
2001
|
+
* The virtual column that stands for a record's rendered title — the entity's
|
|
2002
|
+
* Liquid `title_template` evaluated against the row. Lists show it, and the
|
|
2003
|
+
* records query sorts and filters on it when the template is "simple". No
|
|
2004
|
+
* attribute backs it, so the name is reserved: the backend rejects an
|
|
2005
|
+
* attribute called `record_title` (mirror of `metamodel.RecordTitleField`).
|
|
2006
|
+
*/
|
|
2007
|
+
declare const RECORD_TITLE_FIELD = "record_title";
|
|
2008
|
+
/** True when `name` is taken by a virtual column and unavailable to attributes. */
|
|
2009
|
+
declare function isReservedAttributeName(name: string): boolean;
|
|
2010
|
+
/**
|
|
2011
|
+
* A simple template is literal text plus `{{ attribute }}` references and
|
|
2012
|
+
* nothing else — no filters (`| upcase`), no tags (`{% if %}`), no dotted
|
|
2013
|
+
* references. Only those compile to SQL, so only those make `record_title`
|
|
2014
|
+
* sortable and filterable. Mirror of the Go `titletemplate.ParseSimple`
|
|
2015
|
+
* grammar; the backend stays the authority and answers 400 when the two
|
|
2016
|
+
* ever disagree.
|
|
2017
|
+
*/
|
|
2018
|
+
declare function isTitleQueryable(template: string | undefined): boolean;
|
|
2019
|
+
/** The attributes a simple template references, in order of first use; `[]` otherwise. */
|
|
2020
|
+
declare function titleTemplateVariables(template: string | undefined): string[];
|
|
2021
|
+
|
|
2000
2022
|
/**
|
|
2001
2023
|
* Client for the Proteos Metadata Service API.
|
|
2002
2024
|
* Provides access to all metadata management services.
|
|
@@ -2611,6 +2633,16 @@ declare const EntityContactBindingSchema: z.ZodObject<{
|
|
|
2611
2633
|
}, {
|
|
2612
2634
|
duplicate_policy: "reject" | "flag";
|
|
2613
2635
|
}>;
|
|
2636
|
+
/**
|
|
2637
|
+
* The write-side shape of the contact-binding setting. `duplicate_policy` is
|
|
2638
|
+
* optional here so an EMPTY object can be sent: that is how a writer says
|
|
2639
|
+
* "clear this entity's binding back to null", which is distinct from omitting
|
|
2640
|
+
* the field (which leaves whatever is stored alone). Reads never return the
|
|
2641
|
+
* empty shape — the server stores null instead.
|
|
2642
|
+
*/
|
|
2643
|
+
interface EntityContactBindingInput {
|
|
2644
|
+
duplicate_policy?: ContactBindingDuplicatePolicy;
|
|
2645
|
+
}
|
|
2614
2646
|
interface Entity extends AuditFields {
|
|
2615
2647
|
slug: string;
|
|
2616
2648
|
name: string;
|
|
@@ -2625,8 +2657,10 @@ interface Entity extends AuditFields {
|
|
|
2625
2657
|
*/
|
|
2626
2658
|
public_record_access: PublicAccessOperation[];
|
|
2627
2659
|
/**
|
|
2628
|
-
* Contact-binding setting (see `EntityContactBinding`).
|
|
2629
|
-
*
|
|
2660
|
+
* Contact-binding setting (see `EntityContactBinding`). Absent on every
|
|
2661
|
+
* entity that never declared one — which is most of them, since the setting
|
|
2662
|
+
* is meaningful only alongside a `contact-address` attribute. Absent means
|
|
2663
|
+
* the effective default, `flag`.
|
|
2630
2664
|
*/
|
|
2631
2665
|
contact_binding?: EntityContactBinding;
|
|
2632
2666
|
module_slug: string;
|
|
@@ -3133,9 +3167,12 @@ interface CreateEntityRequest {
|
|
|
3133
3167
|
*/
|
|
3134
3168
|
public_record_access?: PublicAccessOperation[];
|
|
3135
3169
|
/**
|
|
3136
|
-
* Contact-binding setting
|
|
3170
|
+
* Contact-binding setting. Full-replacement on upsert, and its reset target
|
|
3171
|
+
* is ABSENT rather than a materialized default: an upsert that omits the
|
|
3172
|
+
* field clears it back to null, so a manifest that never declares it stays
|
|
3173
|
+
* in sync. Absent behaves as `flag`.
|
|
3137
3174
|
*/
|
|
3138
|
-
contact_binding?:
|
|
3175
|
+
contact_binding?: EntityContactBindingInput;
|
|
3139
3176
|
module_slug: string;
|
|
3140
3177
|
description: string;
|
|
3141
3178
|
title_template?: string;
|
|
@@ -3148,7 +3185,11 @@ interface UpdateEntityRequest {
|
|
|
3148
3185
|
name?: string;
|
|
3149
3186
|
is_remote?: boolean;
|
|
3150
3187
|
public_record_access?: PublicAccessOperation[];
|
|
3151
|
-
|
|
3188
|
+
/**
|
|
3189
|
+
* Omitted leaves the stored binding alone; an EMPTY object clears it back
|
|
3190
|
+
* to null (see `EntityContactBindingInput`).
|
|
3191
|
+
*/
|
|
3192
|
+
contact_binding?: EntityContactBindingInput;
|
|
3152
3193
|
module_slug?: string;
|
|
3153
3194
|
description?: string;
|
|
3154
3195
|
title_template?: string;
|
|
@@ -5724,4 +5765,4 @@ declare function isCurrentUserDefault(value: unknown): value is CurrentUserDefau
|
|
|
5724
5765
|
/** Only the identity-valued attribute types can carry the sentinel. */
|
|
5725
5766
|
declare function acceptsCurrentUserDefault(type: AttributeType): boolean;
|
|
5726
5767
|
|
|
5727
|
-
export { CurrencyAttributeMetaSchema as $, type AuditFields as A, type ComponentService as B, CURRENT_USER_DEFAULT as C, type ContactAddressAttributeKind as D, type ContactAddressAttributeMeta as E, type FileRef as F, ContactAddressAttributeMetaSchema as G, type ContactBindingDuplicatePolicy as H, type CreateAppConfigurationRequest as I, type CreateAppRequest as J, type CreateComponentRequest as K, type ListOptions as L, type CreateDesignReferenceRequest as M, type CreateEntityExtensionRequest as N, type CreateEntityRequest as O, PageIterator as P, type CreateListExtensionRequest as Q, type ResponseMeta as R, type CreateListRequest as S, type CreateListViewRequest as T, type UserRef as U, type CreateMenuConfigurationExtensionRequest as V, type CreateMenuConfigurationRequest as W, type CreatePageExtensionRequest as X, type CreatePageRequest as Y, type CreateVariableRequest as Z, type CurrencyAttributeMeta as _, type Attribute as a, type MenuConfigurationExtensionPlacement as a$, type CurrencySymbolSide as a0, type CurrencyValue as a1, type CurrentUserDefault as a2, DEFAULT_OPTIONS as a3, DEFAULT_PAGE_SIZE as a4, DONE as a5, type DeployModuleRequest as a6, type DesignReference as a7, type DesignReferenceContent as a8, DesignReferenceSchema as a9, type ListDesignReferencesOptions as aA, type ListEntitiesOptions as aB, type ListEntityExtensionsOptions as aC, type ListExtension as aD, type ListExtensionColumnPlacement as aE, ListExtensionColumnPlacementSchema as aF, ListExtensionSchema as aG, type ListExtensionService as aH, type ListFn as aI, type ListListExtensionsOptions as aJ, type ListListViewsOptions as aK, type ListListsOptions as aL, type ListMenuConfigurationExtensionsOptions as aM, type ListMenuConfigurationsOptions as aN, type ListModulesOptions as aO, type ListPageExtensionsOptions as aP, type ListPagesOptions as aQ, ListSchema as aR, type ListService as aS, type ListVariablesOptions as aT, type ListView as aU, ListViewSchema as aV, type ListViewService as aW, type LogicalOperator as aX, MENU_CONFIGURATION_EXTENSION_ANCHOR_ITEMS as aY, type MenuConfiguration as aZ, type MenuConfigurationExtension as a_, type DesignReferenceService as aa, type Done as ab, type Entity as ac, type EntityContactBinding as ad, EntityContactBindingSchema as ae, type EntityExtension as af, EntityExtensionSchema as ag, type EntityExtensionService as ah, EntitySchema as ai, type EntityService as aj, type EntityWithSchema as ak, EntityWithSchemaSchema as al, type EnumAttributeMeta as am, type EnumValue as an, type ExtensionPosition as ao, ExtensionPositionSchema as ap, type FileAttributeMeta as aq, FileRefSchema as ar, type FilterElement as as, FilterElementSchema as at, type FilterGroup as au, FilterGroupSchema as av, type List as aw, type ListAppConfigurationsOptions as ax, type ListAppsOptions as ay, type ListComponentsOptions as az, type ListResult as b, type UserType as b$, MenuConfigurationExtensionPlacementSchema as b0, type MenuConfigurationExtensionPosition as b1, MenuConfigurationExtensionPositionSchema as b2, MenuConfigurationExtensionSchema as b3, type MenuConfigurationExtensionService as b4, MenuConfigurationSchema as b5, type MenuConfigurationService as b6, type MenuItem as b7, MenuItemSchema as b8, MenuItemType as b9, type PublicPageComponent as bA, type PublicPageResponse as bB, type RelationAttributeMeta as bC, RelationAttributeMetaSchema as bD, type RequestOptions as bE, type ResolvedClientOptions as bF, ResponseMetaSchema as bG, type SortConfig as bH, SortConfigSchema as bI, type SortDirection as bJ, type Timestamps as bK, type TokenProvider as bL, type UpdateAppConfigurationRequest as bM, type UpdateAppRequest as bN, type UpdateComponentRequest as bO, type UpdateDesignReferenceRequest as bP, type UpdateEntityExtensionRequest as bQ, type UpdateEntityRequest as bR, type UpdateListExtensionRequest as bS, type UpdateListRequest as bT, type UpdateListViewRequest as bU, type UpdateMenuConfigurationExtensionRequest as bV, type UpdateMenuConfigurationRequest as bW, type UpdatePageExtensionRequest as bX, type UpdatePageRequest as bY, type UpdateVariableRequest as bZ, UserRefSchema as b_, MetaClient as ba, type MetaListOptions as bb, type Module as bc, ModuleSchema as bd, type ModuleService as be, type ModuleStatus as bf, type OnDeleteAction as bg, OnDeleteActionSchema as bh, PAGE_EXTENSION_ANCHOR_MAIN as bi, PAGE_EXTENSION_ANCHOR_SIDE_PANEL as bj, PLATFORM_ATTRIBUTE_NAMES as bk, PLATFORM_USER_ID as bl, type Page as bm, type PageAction as bn, type PageActionKind as bo, PageActionSchema as bp, type PageExtension as bq, type PageExtensionPlacement as br, PageExtensionPlacementSchema as bs, PageExtensionSchema as bt, type PageExtensionService as bu, type PageLayout as bv, PageLayoutSchema as bw, PageSchema as bx, type PageService as by, type PageType as bz, ProteosClient as c,
|
|
5768
|
+
export { CurrencyAttributeMetaSchema as $, type AuditFields as A, type ComponentService as B, CURRENT_USER_DEFAULT as C, type ContactAddressAttributeKind as D, type ContactAddressAttributeMeta as E, type FileRef as F, ContactAddressAttributeMetaSchema as G, type ContactBindingDuplicatePolicy as H, type CreateAppConfigurationRequest as I, type CreateAppRequest as J, type CreateComponentRequest as K, type ListOptions as L, type CreateDesignReferenceRequest as M, type CreateEntityExtensionRequest as N, type CreateEntityRequest as O, PageIterator as P, type CreateListExtensionRequest as Q, type ResponseMeta as R, type CreateListRequest as S, type CreateListViewRequest as T, type UserRef as U, type CreateMenuConfigurationExtensionRequest as V, type CreateMenuConfigurationRequest as W, type CreatePageExtensionRequest as X, type CreatePageRequest as Y, type CreateVariableRequest as Z, type CurrencyAttributeMeta as _, type Attribute as a, type MenuConfigurationExtensionPlacement as a$, type CurrencySymbolSide as a0, type CurrencyValue as a1, type CurrentUserDefault as a2, DEFAULT_OPTIONS as a3, DEFAULT_PAGE_SIZE as a4, DONE as a5, type DeployModuleRequest as a6, type DesignReference as a7, type DesignReferenceContent as a8, DesignReferenceSchema as a9, type ListDesignReferencesOptions as aA, type ListEntitiesOptions as aB, type ListEntityExtensionsOptions as aC, type ListExtension as aD, type ListExtensionColumnPlacement as aE, ListExtensionColumnPlacementSchema as aF, ListExtensionSchema as aG, type ListExtensionService as aH, type ListFn as aI, type ListListExtensionsOptions as aJ, type ListListViewsOptions as aK, type ListListsOptions as aL, type ListMenuConfigurationExtensionsOptions as aM, type ListMenuConfigurationsOptions as aN, type ListModulesOptions as aO, type ListPageExtensionsOptions as aP, type ListPagesOptions as aQ, ListSchema as aR, type ListService as aS, type ListVariablesOptions as aT, type ListView as aU, ListViewSchema as aV, type ListViewService as aW, type LogicalOperator as aX, MENU_CONFIGURATION_EXTENSION_ANCHOR_ITEMS as aY, type MenuConfiguration as aZ, type MenuConfigurationExtension as a_, type DesignReferenceService as aa, type Done as ab, type Entity as ac, type EntityContactBinding as ad, EntityContactBindingSchema as ae, type EntityExtension as af, EntityExtensionSchema as ag, type EntityExtensionService as ah, EntitySchema as ai, type EntityService as aj, type EntityWithSchema as ak, EntityWithSchemaSchema as al, type EnumAttributeMeta as am, type EnumValue as an, type ExtensionPosition as ao, ExtensionPositionSchema as ap, type FileAttributeMeta as aq, FileRefSchema as ar, type FilterElement as as, FilterElementSchema as at, type FilterGroup as au, FilterGroupSchema as av, type List as aw, type ListAppConfigurationsOptions as ax, type ListAppsOptions as ay, type ListComponentsOptions as az, type ListResult as b, type UserType as b$, MenuConfigurationExtensionPlacementSchema as b0, type MenuConfigurationExtensionPosition as b1, MenuConfigurationExtensionPositionSchema as b2, MenuConfigurationExtensionSchema as b3, type MenuConfigurationExtensionService as b4, MenuConfigurationSchema as b5, type MenuConfigurationService as b6, type MenuItem as b7, MenuItemSchema as b8, MenuItemType as b9, type PublicPageComponent as bA, type PublicPageResponse as bB, type RelationAttributeMeta as bC, RelationAttributeMetaSchema as bD, type RequestOptions as bE, type ResolvedClientOptions as bF, ResponseMetaSchema as bG, type SortConfig as bH, SortConfigSchema as bI, type SortDirection as bJ, type Timestamps as bK, type TokenProvider as bL, type UpdateAppConfigurationRequest as bM, type UpdateAppRequest as bN, type UpdateComponentRequest as bO, type UpdateDesignReferenceRequest as bP, type UpdateEntityExtensionRequest as bQ, type UpdateEntityRequest as bR, type UpdateListExtensionRequest as bS, type UpdateListRequest as bT, type UpdateListViewRequest as bU, type UpdateMenuConfigurationExtensionRequest as bV, type UpdateMenuConfigurationRequest as bW, type UpdatePageExtensionRequest as bX, type UpdatePageRequest as bY, type UpdateVariableRequest as bZ, UserRefSchema as b_, MetaClient as ba, type MetaListOptions as bb, type Module as bc, ModuleSchema as bd, type ModuleService as be, type ModuleStatus as bf, type OnDeleteAction as bg, OnDeleteActionSchema as bh, PAGE_EXTENSION_ANCHOR_MAIN as bi, PAGE_EXTENSION_ANCHOR_SIDE_PANEL as bj, PLATFORM_ATTRIBUTE_NAMES as bk, PLATFORM_USER_ID as bl, type Page as bm, type PageAction as bn, type PageActionKind as bo, PageActionSchema as bp, type PageExtension as bq, type PageExtensionPlacement as br, PageExtensionPlacementSchema as bs, PageExtensionSchema as bt, type PageExtensionService as bu, type PageLayout as bv, PageLayoutSchema as bw, PageSchema as bx, type PageService as by, type PageType as bz, ProteosClient as c, type SizeValue as c$, type Variable as c0, VariableSchema as c1, type VariableService as c2, acceptsCurrentUserDefault as c3, allCurrencyCodes as c4, createIterator as c5, createListResultSchema as c6, currencyLabel as c7, currencySymbol as c8, currencySymbolSide as c9, type LayoutAlign as cA, type LayoutElement as cB, LayoutElementSchema as cC, LayoutElementType as cD, type LayoutGap as cE, type LayoutJustify as cF, type LayoutTab as cG, LayoutTabSchema as cH, type ListElement as cI, type NumberAttributeMeta as cJ, type ObjectAttributeMeta as cK, PAGE_BACKGROUND_TOKENS as cL, type PageBackgroundToken as cM, type PageLayoutSidePanel as cN, PageLayoutSidePanelSchema as cO, type PageStyle as cP, PageStyleSchema as cQ, type PrincipalAttributeMeta as cR, type PrincipalType as cS, RECORD_TITLE_FIELD as cT, type RecordFilterElement as cU, type RelatedListElement as cV, type RelatedRecordElement as cW, type ResponsiveSizing as cX, type RowElement as cY, type SchedulingPickerElement as cZ, type SectionElement as c_, formatAmount as ca, formatMoney as cb, isCurrentUserDefault as cc, isPlatformAttributeName as cd, localeNumberSeparators as ce, parseAmount as cf, parseContactAddressMeta as cg, parseCurrencyMeta as ch, parseFileMeta as ci, parseRelationMeta as cj, platformAttributes as ck, resolveOptions as cl, type AttributeForLookup as cm, type AttributeMeta as cn, BUILT_IN_CONTROLS as co, type BuiltInControlSlug as cp, type CardElement as cq, type ColumnElement as cr, type CommonProps as cs, type ComponentElement as ct, type ControlBucket as cu, type DatetimeAttributeMeta as cv, type DatetimeFormat as cw, type DividerElement as cx, type FieldElement as cy, FileAttributeMetaSchema as cz, type PrincipalRef as d, SizeValueSchema as d0, type SizingProps as d1, type StringAttributeMeta as d2, type StringFormat as d3, type TabsElement as d4, type TextElement as d5, type TextVariant as d6, type UserAttributeMeta as d7, UserAttributeMetaSchema as d8, type WorkflowTriggerElement as d9, isBuiltInControl as da, isReservedAttributeName as db, isTitleQueryable as dc, lookupCompatibleControls as dd, lookupControls as de, lookupPrimaryControl as df, parsePrincipalMeta as dg, parseUserMeta as dh, titleTemplateVariables as di, type PublicAccessOperation as e, type App as f, type AppConfiguration as g, AppConfigurationSchema as h, type AppConfigurationService as i, type AppHome as j, AppHomeSchema as k, type AppHomeType as l, AppSchema as m, type AppService as n, type ArrayAttributeMeta as o, type AttributeAccessRule as p, type AttributeRestrictions as q, AttributeSchema as r, type AttributeType as s, AuditFieldsSchema as t, type ClientOptions as u, type Column as v, ColumnSchema as w, type ComparisonOperator as x, type Component as y, ComponentSchema as z };
|
package/package.json
CHANGED
package/src/agent/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ProteosClient } from '../client.js'
|
|
2
2
|
import { type AgentService, AgentServiceImpl } from './agents.js'
|
|
3
3
|
import { type McpServerService, McpServerServiceImpl } from './mcp-servers.js'
|
|
4
|
+
import { type ModelService, ModelServiceImpl } from './models.js'
|
|
4
5
|
import { type PromptService, PromptServiceImpl } from './prompts.js'
|
|
5
6
|
import { type SessionService, SessionServiceImpl } from './sessions.js'
|
|
6
7
|
import { type SkillService, SkillServiceImpl } from './skills.js'
|
|
@@ -12,7 +13,8 @@ import { type ToolsetService, ToolsetServiceImpl } from './toolsets.js'
|
|
|
12
13
|
*
|
|
13
14
|
* Manages the AI-agent configuration domain: Agents, Prompts (versioned),
|
|
14
15
|
* Skills (versioned bundles), Tools, and MCP Servers — all org-scoped and keyed
|
|
15
|
-
* by an immutable kebab-case `key
|
|
16
|
+
* by an immutable kebab-case `key` — plus the stateless model calls
|
|
17
|
+
* (`models.generate`, `models.decide`) and chat sessions.
|
|
16
18
|
*
|
|
17
19
|
* @example
|
|
18
20
|
* ```ts
|
|
@@ -23,6 +25,15 @@ import { type ToolsetService, ToolsetServiceImpl } from './toolsets.js'
|
|
|
23
25
|
*
|
|
24
26
|
* const agents = await agent.agents.list().all();
|
|
25
27
|
* const prompt = await agent.prompts.get('revenue-brief');
|
|
28
|
+
*
|
|
29
|
+
* const { answers } = await agent.models.decide({
|
|
30
|
+
* state: { message: 'My card was charged twice!' },
|
|
31
|
+
* questions: {
|
|
32
|
+
* refund_requested: { type: 'boolean', instructions: 'Does the customer ask for money back?' },
|
|
33
|
+
* topic: { type: 'choice', instructions: 'Topic?', criteria: { billing: 'charges', other: 'else' } },
|
|
34
|
+
* },
|
|
35
|
+
* });
|
|
36
|
+
* if (answers.topic.confidence > 0.8) route(answers.topic.choice);
|
|
26
37
|
* ```
|
|
27
38
|
*/
|
|
28
39
|
export class AgentClient {
|
|
@@ -38,6 +49,8 @@ export class AgentClient {
|
|
|
38
49
|
readonly toolsets: ToolsetService
|
|
39
50
|
/** Service for managing MCP server registrations. */
|
|
40
51
|
readonly mcpServers: McpServerService
|
|
52
|
+
/** Service for stateless model calls: `generate` (one message out) and `decide` (calibrated typed answers). */
|
|
53
|
+
readonly models: ModelService
|
|
41
54
|
/** Service for managing chat sessions (conversations + event log + stream). */
|
|
42
55
|
readonly sessions: SessionService
|
|
43
56
|
|
|
@@ -53,6 +66,7 @@ export class AgentClient {
|
|
|
53
66
|
this.tools = new ToolServiceImpl(client)
|
|
54
67
|
this.toolsets = new ToolsetServiceImpl(client)
|
|
55
68
|
this.mcpServers = new McpServerServiceImpl(client)
|
|
69
|
+
this.models = new ModelServiceImpl(client)
|
|
56
70
|
this.sessions = new SessionServiceImpl(client)
|
|
57
71
|
}
|
|
58
72
|
}
|
|
@@ -60,6 +74,28 @@ export class AgentClient {
|
|
|
60
74
|
// Re-export service interfaces
|
|
61
75
|
export type { AgentService } from './agents.js'
|
|
62
76
|
export type { McpServerService } from './mcp-servers.js'
|
|
77
|
+
// Re-export model-call types (generate + decide)
|
|
78
|
+
export type {
|
|
79
|
+
BooleanAnswer,
|
|
80
|
+
BooleanCriteria,
|
|
81
|
+
BooleanQuestion,
|
|
82
|
+
ChoiceAnswer,
|
|
83
|
+
ChoiceQuestion,
|
|
84
|
+
DecideRequest,
|
|
85
|
+
DecisionAnswer,
|
|
86
|
+
DecisionAnswerFor,
|
|
87
|
+
DecisionQuestion,
|
|
88
|
+
DecisionQuestions,
|
|
89
|
+
DecisionQuestionType,
|
|
90
|
+
DecisionResult,
|
|
91
|
+
GenerateRequest,
|
|
92
|
+
GenerationResult,
|
|
93
|
+
ModelStopReason,
|
|
94
|
+
ScoreAnswer,
|
|
95
|
+
ScoreQuestion,
|
|
96
|
+
StructuredText,
|
|
97
|
+
} from './model-types.js'
|
|
98
|
+
export type { ModelService } from './models.js'
|
|
63
99
|
export type { PromptService } from './prompts.js'
|
|
64
100
|
// Re-export session types
|
|
65
101
|
export type {
|
|
@@ -110,12 +146,14 @@ export type {
|
|
|
110
146
|
CreateMcpServerRequest,
|
|
111
147
|
CreatePromptRequest,
|
|
112
148
|
CreateToolRequest,
|
|
149
|
+
CreateToolsetRequest,
|
|
113
150
|
DependentAgent,
|
|
114
151
|
DependentSyncResult,
|
|
115
152
|
ListAgentsOptions,
|
|
116
153
|
ListMcpServersOptions,
|
|
117
154
|
ListPromptsOptions,
|
|
118
155
|
ListSkillsOptions,
|
|
156
|
+
ListToolsetsOptions,
|
|
119
157
|
ListToolsOptions,
|
|
120
158
|
McpBinding,
|
|
121
159
|
McpConnectionState,
|
|
@@ -125,25 +163,23 @@ export type {
|
|
|
125
163
|
McpServerOAuth,
|
|
126
164
|
McpToolSummary,
|
|
127
165
|
ModelConfig,
|
|
166
|
+
PlatformBinding,
|
|
128
167
|
Prompt,
|
|
129
168
|
PromptVersion,
|
|
169
|
+
QueryBinding,
|
|
130
170
|
Skill,
|
|
131
171
|
SkillBundle,
|
|
132
172
|
SkillVersion,
|
|
133
173
|
StartMcpOAuthResponse,
|
|
134
|
-
PlatformBinding,
|
|
135
|
-
QueryBinding,
|
|
136
174
|
Tool,
|
|
137
175
|
ToolBinding,
|
|
138
176
|
ToolKind,
|
|
139
177
|
Toolset,
|
|
140
178
|
ToolsetKind,
|
|
141
179
|
ToolsetToolSummary,
|
|
142
|
-
CreateToolsetRequest,
|
|
143
|
-
UpdateToolsetRequest,
|
|
144
|
-
ListToolsetsOptions,
|
|
145
180
|
UpdateAgentRequest,
|
|
146
181
|
UpdateMcpServerRequest,
|
|
147
182
|
UpdatePromptRequest,
|
|
148
183
|
UpdateToolRequest,
|
|
184
|
+
UpdateToolsetRequest,
|
|
149
185
|
} from './types.js'
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the stateless model endpoints of the Proteos Agent Service API —
|
|
3
|
+
* `POST /agents/v1/models/generate` and `POST /agents/v1/models/decide`.
|
|
4
|
+
*
|
|
5
|
+
* Hand-written mirror of the Go models in `go.proteos.ai/model/agent`
|
|
6
|
+
* (`generation.go`, `decision.go` + `api/generation-requests.go`,
|
|
7
|
+
* `api/decision-requests.go`). Field names match the snake_case wire format
|
|
8
|
+
* exactly, including enum values.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ContentBlock, ModelUsage, TextBlock } from './session-types.js'
|
|
12
|
+
import type { ModelConfig } from './types.js'
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Generation (one message out)
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Why the model stopped generating. An open string so a new provider reason
|
|
20
|
+
* never breaks decoding; the key distinction is `end_turn` (complete) vs
|
|
21
|
+
* `max_tokens` (truncated).
|
|
22
|
+
*/
|
|
23
|
+
export type ModelStopReason = 'end_turn' | 'max_tokens' | 'stop_sequence' | (string & {})
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Body of `POST /agents/v1/models/generate` — a single, stateless model call:
|
|
27
|
+
* content blocks in, one assistant message out. No event log, no tools, no
|
|
28
|
+
* multi-turn state.
|
|
29
|
+
*/
|
|
30
|
+
export interface GenerateRequest {
|
|
31
|
+
/** Model id + sampling knobs. Omitted (or an empty `model_id`) resolves to the service default. */
|
|
32
|
+
model?: Partial<ModelConfig>
|
|
33
|
+
/** Optional system prompt steering the response. */
|
|
34
|
+
system?: string
|
|
35
|
+
/** The message body the model answers — text and file blocks (a file-only body is valid). */
|
|
36
|
+
content: ContentBlock[]
|
|
37
|
+
/**
|
|
38
|
+
* JSON Schema of the structured reply. When set, generation is forced through a
|
|
39
|
+
* schema-constrained tool and the structured value comes back as `output`.
|
|
40
|
+
*/
|
|
41
|
+
output_schema?: Record<string, unknown>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The assistant's reply to a {@link GenerateRequest}. */
|
|
45
|
+
export interface GenerationResult {
|
|
46
|
+
/** The returned text blocks (usually empty on a schema-constrained call). */
|
|
47
|
+
content: TextBlock[]
|
|
48
|
+
stop_reason?: ModelStopReason
|
|
49
|
+
/** The model that produced the reply (resolved id). */
|
|
50
|
+
model_id: string
|
|
51
|
+
usage: ModelUsage
|
|
52
|
+
/** The structured value of a schema-constrained generation; absent otherwise. */
|
|
53
|
+
output?: unknown
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Decisions (typed, calibrated answers out — no prose)
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The text shape a decision provider reads: a string, a JSON object, or an
|
|
62
|
+
* array — never `null`, a number, or a boolean. Carries the state under
|
|
63
|
+
* judgment, a question's instructions, every criteria description, and the
|
|
64
|
+
* legend echoed back on a score. Structure passes through verbatim, so
|
|
65
|
+
* instructions can be structured guidance (named fields such as `what` /
|
|
66
|
+
* `not_for` / `examples`, backtick paths into the state like
|
|
67
|
+
* `` `ticket.messages[0].text` ``).
|
|
68
|
+
*/
|
|
69
|
+
export type StructuredText = string | Record<string, unknown> | unknown[]
|
|
70
|
+
|
|
71
|
+
/** Discriminates a {@link DecisionQuestion} and its {@link DecisionAnswer}. */
|
|
72
|
+
export type DecisionQuestionType = 'boolean' | 'choice' | 'score'
|
|
73
|
+
|
|
74
|
+
/** Describes the two outcomes of a {@link BooleanQuestion}. */
|
|
75
|
+
export interface BooleanCriteria {
|
|
76
|
+
true: StructuredText
|
|
77
|
+
false: StructuredText
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* "Is this statement true?" — answered with the calibrated probability that it
|
|
82
|
+
* is. `criteria` optionally spells out what makes the statement hold (true) or
|
|
83
|
+
* not (false) when the boundary is subtle.
|
|
84
|
+
*/
|
|
85
|
+
export interface BooleanQuestion {
|
|
86
|
+
type: 'boolean'
|
|
87
|
+
instructions: StructuredText
|
|
88
|
+
criteria?: BooleanCriteria
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* "Which one of these?" — `criteria` maps each option name to its description;
|
|
93
|
+
* options are unordered. Option-count limits are the provider's.
|
|
94
|
+
*/
|
|
95
|
+
export interface ChoiceQuestion<Option extends string = string> {
|
|
96
|
+
type: 'choice'
|
|
97
|
+
instructions: StructuredText
|
|
98
|
+
criteria: Record<Option, StructuredText>
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* "Where on this scale?" — `criteria` is the ordered list of level
|
|
103
|
+
* descriptions; the level number is the position (0-based). Every level must
|
|
104
|
+
* be described. Level-count limits are the provider's.
|
|
105
|
+
*/
|
|
106
|
+
export interface ScoreQuestion {
|
|
107
|
+
type: 'score'
|
|
108
|
+
instructions: StructuredText
|
|
109
|
+
criteria: StructuredText[]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** One atomic question over the shared state, discriminated by `type`. */
|
|
113
|
+
export type DecisionQuestion = BooleanQuestion | ChoiceQuestion | ScoreQuestion
|
|
114
|
+
|
|
115
|
+
/** Caller-keyed questions; answers come back under the same keys. */
|
|
116
|
+
export type DecisionQuestions = Record<string, DecisionQuestion>
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Body of `POST /agents/v1/models/decide` — one text-only state and a map of
|
|
120
|
+
* atomic questions answered in parallel with calibrated probabilities.
|
|
121
|
+
*
|
|
122
|
+
* Only `model.model_id` is meaningful for a decision; the sampling knobs of
|
|
123
|
+
* {@link ModelConfig} are rejected with `invalid_decision_request`.
|
|
124
|
+
*/
|
|
125
|
+
export interface DecideRequest<Questions extends DecisionQuestions = DecisionQuestions> {
|
|
126
|
+
model?: Partial<Pick<ModelConfig, 'model_id'>>
|
|
127
|
+
state: StructuredText
|
|
128
|
+
questions: Questions
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Answer to a {@link BooleanQuestion}: `probability` is P(true); `boolean` is
|
|
133
|
+
* the argmax (probability > 0.5); `confidence` is |2p − 1|.
|
|
134
|
+
*/
|
|
135
|
+
export interface BooleanAnswer {
|
|
136
|
+
type: 'boolean'
|
|
137
|
+
boolean: boolean
|
|
138
|
+
probability: number
|
|
139
|
+
confidence: number
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Answer to a {@link ChoiceQuestion}: `choice` is the highest-probability
|
|
144
|
+
* option; `probabilities` is the full distribution keyed by option name.
|
|
145
|
+
*/
|
|
146
|
+
export interface ChoiceAnswer<Option extends string = string> {
|
|
147
|
+
type: 'choice'
|
|
148
|
+
choice: Option
|
|
149
|
+
probabilities: Record<Option, number>
|
|
150
|
+
confidence: number
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Answer to a {@link ScoreQuestion}: `score` is the probability-weighted mean
|
|
155
|
+
* of the level numbers (so it can fall between levels); `legend` echoes the
|
|
156
|
+
* level descriptions and `probabilities` the distribution, both indexed by
|
|
157
|
+
* level.
|
|
158
|
+
*/
|
|
159
|
+
export interface ScoreAnswer {
|
|
160
|
+
type: 'score'
|
|
161
|
+
score: number
|
|
162
|
+
legend: StructuredText[]
|
|
163
|
+
probabilities: number[]
|
|
164
|
+
confidence: number
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The calibrated answer to one question, discriminated by `type`. Every
|
|
169
|
+
* variant carries `confidence` = (n·peak − 1)/(n − 1) over its distribution,
|
|
170
|
+
* so gating code can threshold without switching on the type.
|
|
171
|
+
*/
|
|
172
|
+
export type DecisionAnswer = BooleanAnswer | ChoiceAnswer | ScoreAnswer
|
|
173
|
+
|
|
174
|
+
/** The answer type a given question produces (drives typed `answers`). */
|
|
175
|
+
export type DecisionAnswerFor<Question extends DecisionQuestion> = Question extends BooleanQuestion
|
|
176
|
+
? BooleanAnswer
|
|
177
|
+
: Question extends ChoiceQuestion<infer Option>
|
|
178
|
+
? ChoiceAnswer<Option>
|
|
179
|
+
: Question extends ScoreQuestion
|
|
180
|
+
? ScoreAnswer
|
|
181
|
+
: never
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The provider's reply to a {@link DecideRequest}: one answer per question key
|
|
185
|
+
* (typed from the questions you sent), the model that produced them, and token
|
|
186
|
+
* usage.
|
|
187
|
+
*/
|
|
188
|
+
export interface DecisionResult<Questions extends DecisionQuestions = DecisionQuestions> {
|
|
189
|
+
/** The model that produced the answers (resolved id, e.g. `jev-1.13.0`). */
|
|
190
|
+
model_id: string
|
|
191
|
+
answers: { [Key in keyof Questions]: DecisionAnswerFor<Questions[Key]> }
|
|
192
|
+
usage: ModelUsage
|
|
193
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ProteosClient } from '../client.js'
|
|
2
|
+
import type {
|
|
3
|
+
DecideRequest,
|
|
4
|
+
DecisionQuestions,
|
|
5
|
+
DecisionResult,
|
|
6
|
+
GenerateRequest,
|
|
7
|
+
GenerationResult,
|
|
8
|
+
} from './model-types.js'
|
|
9
|
+
|
|
10
|
+
const MODELS_BASE_PATH = '/agents/v1/models'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Service for the stateless model calls — one request in, one reply out, no
|
|
14
|
+
* session, no event log:
|
|
15
|
+
*
|
|
16
|
+
* - `generate` — free text or schema-constrained structured output from an LLM.
|
|
17
|
+
* - `decide` — calibrated typed answers (boolean | choice | score) with
|
|
18
|
+
* probabilities and confidence, for snap judgments inside code paths
|
|
19
|
+
* (routing, triage, classification, gates). No prose comes back; compose the
|
|
20
|
+
* answers in code and threshold on `confidence`.
|
|
21
|
+
*
|
|
22
|
+
* Both need the `agent-sessions:write` permission.
|
|
23
|
+
*/
|
|
24
|
+
export interface ModelService {
|
|
25
|
+
/**
|
|
26
|
+
* Runs a single model call and returns the assistant message.
|
|
27
|
+
* @throws {ProteosError} 400 `invalid_generation_request` / `unsupported_file_type` /
|
|
28
|
+
* `model_provider_rejected_request`; 429 `model_provider_rate_limited`;
|
|
29
|
+
* 502 `model_provider_failed`.
|
|
30
|
+
*/
|
|
31
|
+
generate(request: GenerateRequest): Promise<GenerationResult>
|
|
32
|
+
/**
|
|
33
|
+
* Answers typed questions about a text state with calibrated probabilities.
|
|
34
|
+
* `answers` is typed from the `questions` you pass, so
|
|
35
|
+
* `result.answers.topic.choice` narrows to the option names you declared.
|
|
36
|
+
*
|
|
37
|
+
* Semantic limits (option / level counts, empty questions, unknown model ids)
|
|
38
|
+
* are the provider's and surface as `decision_provider_rejected_request` with
|
|
39
|
+
* its message.
|
|
40
|
+
* @throws {ProteosError} 400 `invalid_decision_request` (shape) /
|
|
41
|
+
* `decision_provider_rejected_request` (provider rule); 429
|
|
42
|
+
* `decision_provider_rate_limited`; 502 `decision_provider_failed` /
|
|
43
|
+
* `decision_provider_invalid_response`; 503 `decision_provider_unavailable`
|
|
44
|
+
* when the provider key is not configured.
|
|
45
|
+
*/
|
|
46
|
+
decide<Questions extends DecisionQuestions>(
|
|
47
|
+
request: DecideRequest<Questions>,
|
|
48
|
+
): Promise<DecisionResult<Questions>>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class ModelServiceImpl implements ModelService {
|
|
52
|
+
constructor(private readonly client: ProteosClient) {}
|
|
53
|
+
|
|
54
|
+
async generate(request: GenerateRequest): Promise<GenerationResult> {
|
|
55
|
+
return this.client.request<GenerationResult>('POST', `${MODELS_BASE_PATH}/generate`, request)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async decide<Questions extends DecisionQuestions>(
|
|
59
|
+
request: DecideRequest<Questions>,
|
|
60
|
+
): Promise<DecisionResult<Questions>> {
|
|
61
|
+
return this.client.request<DecisionResult<Questions>>(
|
|
62
|
+
'POST',
|
|
63
|
+
`${MODELS_BASE_PATH}/decide`,
|
|
64
|
+
request,
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* @packageDocumentation
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
-
// Agent client (agent-service: agents, prompts, skills, tools, mcp-servers, sessions)
|
|
37
|
+
// Agent client (agent-service: agents, prompts, skills, tools, mcp-servers, models, sessions)
|
|
38
38
|
export type {
|
|
39
39
|
ActionBinding,
|
|
40
40
|
Agent,
|
|
@@ -43,6 +43,11 @@ export type {
|
|
|
43
43
|
AgentResourceListOptions,
|
|
44
44
|
AgentService,
|
|
45
45
|
AppendEventRequest,
|
|
46
|
+
BooleanAnswer,
|
|
47
|
+
BooleanCriteria,
|
|
48
|
+
BooleanQuestion,
|
|
49
|
+
ChoiceAnswer,
|
|
50
|
+
ChoiceQuestion,
|
|
46
51
|
ClientEventType,
|
|
47
52
|
ClientToolSchema,
|
|
48
53
|
ContentBlock,
|
|
@@ -53,12 +58,21 @@ export type {
|
|
|
53
58
|
CreateSessionRequest,
|
|
54
59
|
CreateToolRequest,
|
|
55
60
|
CreateToolsetRequest,
|
|
61
|
+
DecideRequest,
|
|
62
|
+
DecisionAnswer,
|
|
63
|
+
DecisionAnswerFor,
|
|
64
|
+
DecisionQuestion,
|
|
65
|
+
DecisionQuestions,
|
|
66
|
+
DecisionQuestionType,
|
|
67
|
+
DecisionResult,
|
|
56
68
|
DependentAgent,
|
|
57
69
|
DependentSyncResult,
|
|
58
70
|
EmptyPayload,
|
|
59
71
|
ErrorPayload,
|
|
60
72
|
EventType,
|
|
61
73
|
FileBlock,
|
|
74
|
+
GenerateRequest,
|
|
75
|
+
GenerationResult,
|
|
62
76
|
ListAgentsOptions,
|
|
63
77
|
ListMcpServersOptions,
|
|
64
78
|
ListPromptsOptions,
|
|
@@ -77,6 +91,8 @@ export type {
|
|
|
77
91
|
ModelConfig,
|
|
78
92
|
ModelRequestEndPayload,
|
|
79
93
|
ModelRequestStartPayload,
|
|
94
|
+
ModelService,
|
|
95
|
+
ModelStopReason,
|
|
80
96
|
ModelUsage,
|
|
81
97
|
PlatformBinding,
|
|
82
98
|
Prompt,
|
|
@@ -85,6 +101,8 @@ export type {
|
|
|
85
101
|
QueryBinding,
|
|
86
102
|
ReasoningPayload,
|
|
87
103
|
ResultBlock,
|
|
104
|
+
ScoreAnswer,
|
|
105
|
+
ScoreQuestion,
|
|
88
106
|
Session,
|
|
89
107
|
SessionEvent,
|
|
90
108
|
SessionEventEnvelope,
|
|
@@ -100,6 +118,7 @@ export type {
|
|
|
100
118
|
SkillVersion,
|
|
101
119
|
StartMcpOAuthResponse,
|
|
102
120
|
StopReason,
|
|
121
|
+
StructuredText,
|
|
103
122
|
TextBlock,
|
|
104
123
|
Tool,
|
|
105
124
|
ToolBinding,
|
package/src/meta/index.ts
CHANGED
|
@@ -164,6 +164,12 @@ export type { MenuConfigurationService } from './menu-configurations.js'
|
|
|
164
164
|
export type { ModuleService } from './modules.js'
|
|
165
165
|
export type { PageExtensionService } from './page-extensions.js'
|
|
166
166
|
export type { PageService } from './pages.js'
|
|
167
|
+
export {
|
|
168
|
+
isReservedAttributeName,
|
|
169
|
+
isTitleQueryable,
|
|
170
|
+
RECORD_TITLE_FIELD,
|
|
171
|
+
titleTemplateVariables,
|
|
172
|
+
} from './record-title.js'
|
|
167
173
|
// Re-export types
|
|
168
174
|
export type {
|
|
169
175
|
// App types
|
|
@@ -276,7 +276,7 @@ export type SchedulingPickerElement = CommonProps & {
|
|
|
276
276
|
is_header_hidden?: boolean
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
export type TextVariant = 'heading' | 'subheading' | 'body' | 'caption' | 'callout'
|
|
279
|
+
export type TextVariant = 'heading' | 'subheading' | 'body' | 'caption' | 'callout' | 'block-title'
|
|
280
280
|
|
|
281
281
|
export type TextElement = CommonProps & {
|
|
282
282
|
type: 'text'
|
|
@@ -427,7 +427,7 @@ export const LayoutElementSchema: z.ZodType<LayoutElement> = z.lazy(() =>
|
|
|
427
427
|
z.object({
|
|
428
428
|
type: z.literal('text'),
|
|
429
429
|
...commonPropsShape,
|
|
430
|
-
variant: z.enum(['heading', 'subheading', 'body', 'caption', 'callout']),
|
|
430
|
+
variant: z.enum(['heading', 'subheading', 'body', 'caption', 'callout', 'block-title']),
|
|
431
431
|
content: z.string().min(1),
|
|
432
432
|
}),
|
|
433
433
|
z.object({
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The virtual column that stands for a record's rendered title — the entity's
|
|
3
|
+
* Liquid `title_template` evaluated against the row. Lists show it, and the
|
|
4
|
+
* records query sorts and filters on it when the template is "simple". No
|
|
5
|
+
* attribute backs it, so the name is reserved: the backend rejects an
|
|
6
|
+
* attribute called `record_title` (mirror of `metamodel.RecordTitleField`).
|
|
7
|
+
*/
|
|
8
|
+
export const RECORD_TITLE_FIELD = 'record_title'
|
|
9
|
+
|
|
10
|
+
/** True when `name` is taken by a virtual column and unavailable to attributes. */
|
|
11
|
+
export function isReservedAttributeName(name: string): boolean {
|
|
12
|
+
return name === RECORD_TITLE_FIELD
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A simple template is literal text plus `{{ attribute }}` references and
|
|
17
|
+
* nothing else — no filters (`| upcase`), no tags (`{% if %}`), no dotted
|
|
18
|
+
* references. Only those compile to SQL, so only those make `record_title`
|
|
19
|
+
* sortable and filterable. Mirror of the Go `titletemplate.ParseSimple`
|
|
20
|
+
* grammar; the backend stays the authority and answers 400 when the two
|
|
21
|
+
* ever disagree.
|
|
22
|
+
*/
|
|
23
|
+
export function isTitleQueryable(template: string | undefined): boolean {
|
|
24
|
+
// Nothing to order or match on without at least one attribute reference.
|
|
25
|
+
if (!template?.includes('{{')) return false
|
|
26
|
+
if (template.includes('{%') || template.includes('%}')) return false
|
|
27
|
+
let rest = template
|
|
28
|
+
while (rest !== '') {
|
|
29
|
+
const open = rest.indexOf('{{')
|
|
30
|
+
if (open < 0) return !rest.includes('}}')
|
|
31
|
+
if (rest.slice(0, open).includes('}}')) return false
|
|
32
|
+
rest = rest.slice(open + 2)
|
|
33
|
+
const close = rest.indexOf('}}')
|
|
34
|
+
if (close < 0) return false
|
|
35
|
+
if (!/^[a-z][a-z0-9_]*$/.test(rest.slice(0, close).trim())) return false
|
|
36
|
+
rest = rest.slice(close + 2)
|
|
37
|
+
}
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The attributes a simple template references, in order of first use; `[]` otherwise. */
|
|
42
|
+
export function titleTemplateVariables(template: string | undefined): string[] {
|
|
43
|
+
if (!template || !isTitleQueryable(template)) return []
|
|
44
|
+
const out: string[] = []
|
|
45
|
+
for (const match of template.matchAll(/\{\{\s*([a-z][a-z0-9_]*)\s*\}\}/g)) {
|
|
46
|
+
const name = match[1]
|
|
47
|
+
if (name && !out.includes(name)) out.push(name)
|
|
48
|
+
}
|
|
49
|
+
return out
|
|
50
|
+
}
|