@rippling/rippling-sdk 0.2.0-alpha.78 → 0.2.0-alpha.80
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/client.d.mts +2 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +2 -2
- package/client.d.ts.map +1 -1
- package/client.js.map +1 -1
- package/client.mjs.map +1 -1
- package/examples/manifest/custom-skill/custom-skill.ts +45 -0
- package/lib/manifest/agent.d.mts +60 -0
- package/lib/manifest/agent.d.mts.map +1 -0
- package/lib/manifest/agent.d.ts +60 -0
- package/lib/manifest/agent.d.ts.map +1 -0
- package/lib/manifest/agent.js +94 -0
- package/lib/manifest/agent.js.map +1 -0
- package/lib/manifest/agent.mjs +90 -0
- package/lib/manifest/agent.mjs.map +1 -0
- package/lib/manifest/custom-field.d.mts +56 -15
- package/lib/manifest/custom-field.d.mts.map +1 -1
- package/lib/manifest/custom-field.d.ts +56 -15
- package/lib/manifest/custom-field.d.ts.map +1 -1
- package/lib/manifest/custom-field.js +27 -0
- package/lib/manifest/custom-field.js.map +1 -1
- package/lib/manifest/custom-field.mjs +27 -0
- package/lib/manifest/custom-field.mjs.map +1 -1
- package/lib/manifest/custom-skill.d.mts +115 -0
- package/lib/manifest/custom-skill.d.mts.map +1 -0
- package/lib/manifest/custom-skill.d.ts +115 -0
- package/lib/manifest/custom-skill.d.ts.map +1 -0
- package/lib/manifest/custom-skill.js +127 -0
- package/lib/manifest/custom-skill.js.map +1 -0
- package/lib/manifest/custom-skill.mjs +123 -0
- package/lib/manifest/custom-skill.mjs.map +1 -0
- package/lib/manifest/existing-manifest-context.d.mts +7 -0
- package/lib/manifest/existing-manifest-context.d.mts.map +1 -1
- package/lib/manifest/existing-manifest-context.d.ts +7 -0
- package/lib/manifest/existing-manifest-context.d.ts.map +1 -1
- package/lib/manifest/existing-manifest-context.js +34 -0
- package/lib/manifest/existing-manifest-context.js.map +1 -1
- package/lib/manifest/existing-manifest-context.mjs +34 -0
- package/lib/manifest/existing-manifest-context.mjs.map +1 -1
- package/lib/manifest/index.d.mts +3 -1
- package/lib/manifest/index.d.mts.map +1 -1
- package/lib/manifest/index.d.ts +3 -1
- package/lib/manifest/index.d.ts.map +1 -1
- package/lib/manifest/index.js +5 -1
- package/lib/manifest/index.js.map +1 -1
- package/lib/manifest/index.mjs +2 -0
- package/lib/manifest/index.mjs.map +1 -1
- package/lib/manifest/manifest-builder.d.mts +1 -1
- package/lib/manifest/manifest-builder.d.mts.map +1 -1
- package/lib/manifest/manifest-builder.d.ts +1 -1
- package/lib/manifest/manifest-builder.d.ts.map +1 -1
- package/lib/manifest/manifest-builder.js.map +1 -1
- package/lib/manifest/manifest-builder.mjs.map +1 -1
- package/package.json +1 -1
- package/resources/index.d.mts +1 -1
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +1 -1
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs.map +1 -1
- package/resources/leave-program-evaluations.d.mts +32 -2
- package/resources/leave-program-evaluations.d.mts.map +1 -1
- package/resources/leave-program-evaluations.d.ts +32 -2
- package/resources/leave-program-evaluations.d.ts.map +1 -1
- package/resources/teams.d.mts +33 -1
- package/resources/teams.d.mts.map +1 -1
- package/resources/teams.d.ts +33 -1
- package/resources/teams.d.ts.map +1 -1
- package/resources/teams.js +22 -0
- package/resources/teams.js.map +1 -1
- package/resources/teams.mjs +22 -0
- package/resources/teams.mjs.map +1 -1
- package/src/client.ts +4 -0
- package/src/lib/manifest/agent.ts +141 -0
- package/src/lib/manifest/custom-field.ts +140 -26
- package/src/lib/manifest/custom-skill.ts +205 -0
- package/src/lib/manifest/existing-manifest-context.ts +61 -0
- package/src/lib/manifest/index.ts +18 -0
- package/src/lib/manifest/manifest-builder.ts +2 -0
- package/src/resources/index.ts +2 -0
- package/src/resources/leave-program-evaluations.ts +38 -2
- package/src/resources/teams.ts +55 -0
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -68,38 +68,106 @@ export type CustomFieldDefaultValue =
|
|
|
68
68
|
| { value: string; rqlDefinitionFormula?: never }
|
|
69
69
|
| { value?: never; rqlDefinitionFormula: string };
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
/** Properties shared by formula and user-input custom fields. */
|
|
72
|
+
export interface CustomFieldBaseProps<ModelRqlName extends string = string> {
|
|
72
73
|
fieldId?: string;
|
|
73
74
|
name: string;
|
|
74
75
|
section: CustomFieldSection;
|
|
75
|
-
modelRqlName:
|
|
76
|
+
modelRqlName: ModelRqlName;
|
|
76
77
|
dataType: CustomFieldDataType;
|
|
77
78
|
apiName: CustomFieldApiName;
|
|
79
|
+
description?: string | null;
|
|
80
|
+
displayOrder?: number | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type NonSensitiveCustomFieldPermissionClassification = Exclude<
|
|
84
|
+
CustomFieldPermissionClassification,
|
|
85
|
+
'SENSITIVE_PERSONAL_INFO' | 'SENSITIVE_EMPLOYMENT_INFO'
|
|
86
|
+
>;
|
|
87
|
+
|
|
88
|
+
/** Permission properties required for every Employee custom field. */
|
|
89
|
+
export type EmployeeCustomFieldPermissionProps = { applicableGroup: string } & (
|
|
90
|
+
| {
|
|
91
|
+
fieldReadAccess: 'ALL_ACCESS';
|
|
92
|
+
fieldPermissionClassification: NonSensitiveCustomFieldPermissionClassification;
|
|
93
|
+
}
|
|
94
|
+
| {
|
|
95
|
+
fieldReadAccess: 'ADMIN_ACCESS' | 'ADMIN_AND_EMPLOYEE_ACCESS';
|
|
96
|
+
fieldPermissionClassification: CustomFieldPermissionClassification;
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
/** Optional permission properties used by non-Employee custom fields. */
|
|
101
|
+
export interface NonEmployeeCustomFieldPermissionProps {
|
|
78
102
|
fieldPermissionClassification?: CustomFieldPermissionClassification | null;
|
|
79
103
|
fieldReadAccess?: CustomFieldReadAccess | null;
|
|
80
|
-
fieldWriteAccess?: CustomFieldWriteAccess | null;
|
|
81
104
|
applicableGroup?: string | null;
|
|
82
|
-
description?: string | null;
|
|
83
|
-
displayOrder?: number | null;
|
|
84
105
|
}
|
|
85
106
|
|
|
86
|
-
export type
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
export type CustomFieldPermissionProps<ModelRqlName extends string = string> =
|
|
108
|
+
ModelRqlName extends 'Employee' ? EmployeeCustomFieldPermissionProps
|
|
109
|
+
: NonEmployeeCustomFieldPermissionProps;
|
|
110
|
+
|
|
111
|
+
interface CustomFieldUserInputOptions {
|
|
112
|
+
rqlDefinitionFormula?: null;
|
|
113
|
+
required?: boolean | null;
|
|
114
|
+
tip?: string | null;
|
|
115
|
+
defaultValue?: CustomFieldDefaultValue | null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type EmployeeCustomFieldUserInputAccess =
|
|
119
|
+
| {
|
|
120
|
+
collectDuring: 'ONBOARDING';
|
|
121
|
+
fieldReadAccess: 'ALL_ACCESS' | 'ADMIN_AND_EMPLOYEE_ACCESS';
|
|
122
|
+
fieldWriteAccess: 'EMPLOYEE_ACCESS' | 'ADMIN_AND_EMPLOYEE_ACCESS' | 'NO_ACCESS';
|
|
123
|
+
}
|
|
124
|
+
| {
|
|
125
|
+
collectDuring?: 'NONE' | 'HIRING' | 'TERMINATING' | null;
|
|
126
|
+
fieldWriteAccess: CustomFieldWriteAccess;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
interface NonEmployeeCustomFieldUserInputAccess {
|
|
130
|
+
collectDuring?: CustomFieldCollectionTiming | null;
|
|
131
|
+
fieldWriteAccess?: CustomFieldWriteAccess | null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
type CustomFieldUserInputAccess<ModelRqlName extends string> =
|
|
135
|
+
ModelRqlName extends 'Employee' ? EmployeeCustomFieldUserInputAccess
|
|
136
|
+
: NonEmployeeCustomFieldUserInputAccess;
|
|
137
|
+
|
|
138
|
+
interface CustomFieldFormulaOptions {
|
|
139
|
+
rqlDefinitionFormula: string;
|
|
140
|
+
fieldWriteAccess: 'NO_ACCESS';
|
|
141
|
+
collectDuring?: null;
|
|
142
|
+
required?: null;
|
|
143
|
+
tip?: null;
|
|
144
|
+
defaultValue?: null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** A calculated custom field whose value cannot be edited directly. */
|
|
148
|
+
export type FormulaCustomFieldProps<ModelRqlName extends string = string> =
|
|
149
|
+
CustomFieldBaseProps<ModelRqlName> & CustomFieldPermissionProps<ModelRqlName> & CustomFieldFormulaOptions;
|
|
150
|
+
|
|
151
|
+
/** A custom field whose value is supplied by a user or a default value. */
|
|
152
|
+
export type UserInputCustomFieldProps<ModelRqlName extends string = string> =
|
|
153
|
+
CustomFieldBaseProps<ModelRqlName> &
|
|
154
|
+
CustomFieldPermissionProps<ModelRqlName> &
|
|
155
|
+
CustomFieldUserInputOptions &
|
|
156
|
+
CustomFieldUserInputAccess<ModelRqlName>;
|
|
157
|
+
|
|
158
|
+
/** A formula or user-input custom field on the given model. */
|
|
159
|
+
export type CustomFieldProps<ModelRqlName extends string = string> =
|
|
160
|
+
| FormulaCustomFieldProps<ModelRqlName>
|
|
161
|
+
| UserInputCustomFieldProps<ModelRqlName>;
|
|
162
|
+
|
|
163
|
+
/** A calculated Employee custom field. */
|
|
164
|
+
export type EmployeeFormulaCustomFieldProps = FormulaCustomFieldProps<'Employee'>;
|
|
165
|
+
|
|
166
|
+
/** An Employee custom field whose value is supplied by a user or a default value. */
|
|
167
|
+
export type EmployeeUserInputCustomFieldProps = UserInputCustomFieldProps<'Employee'>;
|
|
168
|
+
|
|
169
|
+
/** Any supported Employee custom field. */
|
|
170
|
+
export type EmployeeCustomFieldProps = EmployeeFormulaCustomFieldProps | EmployeeUserInputCustomFieldProps;
|
|
103
171
|
|
|
104
172
|
function cloneJson<T>(value: T): T {
|
|
105
173
|
if (value == null) return value;
|
|
@@ -153,7 +221,7 @@ function customFieldDataTypeFromWire(dataType: Record<string, any>): CustomField
|
|
|
153
221
|
}
|
|
154
222
|
|
|
155
223
|
/** A Custom Field V2 field on a native or custom object. */
|
|
156
|
-
export class CustomField {
|
|
224
|
+
export class CustomField<const ModelRqlName extends string = string> {
|
|
157
225
|
static readonly componentType = 'CUSTOM_FIELD_V2' as const;
|
|
158
226
|
|
|
159
227
|
static toDeletionIdentifier(customFieldId: string): ManifestComponentDeletion {
|
|
@@ -161,9 +229,17 @@ export class CustomField {
|
|
|
161
229
|
}
|
|
162
230
|
|
|
163
231
|
private readonly _fieldId: string;
|
|
164
|
-
private readonly props: CustomFieldProps
|
|
232
|
+
private readonly props: CustomFieldProps<ModelRqlName>;
|
|
165
233
|
|
|
166
|
-
constructor(scope: ManifestScope, props: CustomFieldProps) {
|
|
234
|
+
constructor(scope: ManifestScope, props: CustomFieldProps<ModelRqlName>) {
|
|
235
|
+
const runtimeProps = props as CustomFieldBaseProps<string> & {
|
|
236
|
+
fieldPermissionClassification?: CustomFieldPermissionClassification | null;
|
|
237
|
+
fieldReadAccess?: CustomFieldReadAccess | null;
|
|
238
|
+
fieldWriteAccess?: CustomFieldWriteAccess | null;
|
|
239
|
+
applicableGroup?: string | null;
|
|
240
|
+
collectDuring?: CustomFieldCollectionTiming | null;
|
|
241
|
+
rqlDefinitionFormula?: string | null;
|
|
242
|
+
};
|
|
167
243
|
if (!props.apiName.endsWith('__cfv2')) {
|
|
168
244
|
throw new Error(`Custom Field V2 api_name must end with __cfv2: ${props.apiName}`);
|
|
169
245
|
}
|
|
@@ -173,11 +249,45 @@ export class CustomField {
|
|
|
173
249
|
`but the field belongs to "${props.modelRqlName}".`,
|
|
174
250
|
);
|
|
175
251
|
}
|
|
252
|
+
if (runtimeProps.rqlDefinitionFormula != null && runtimeProps.fieldWriteAccess !== 'NO_ACCESS') {
|
|
253
|
+
throw new Error(`Formula custom field "${props.apiName}" must have fieldWriteAccess "NO_ACCESS".`);
|
|
254
|
+
}
|
|
255
|
+
if (props.modelRqlName === 'Employee') {
|
|
256
|
+
if (
|
|
257
|
+
runtimeProps.fieldPermissionClassification == null ||
|
|
258
|
+
runtimeProps.fieldReadAccess == null ||
|
|
259
|
+
runtimeProps.fieldWriteAccess == null ||
|
|
260
|
+
runtimeProps.applicableGroup == null
|
|
261
|
+
) {
|
|
262
|
+
throw new Error(
|
|
263
|
+
`Employee custom field "${props.apiName}" requires fieldPermissionClassification, ` +
|
|
264
|
+
`fieldReadAccess, fieldWriteAccess, and applicableGroup.`,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
if (
|
|
268
|
+
runtimeProps.fieldReadAccess === 'ALL_ACCESS' &&
|
|
269
|
+
(runtimeProps.fieldPermissionClassification === 'SENSITIVE_PERSONAL_INFO' ||
|
|
270
|
+
runtimeProps.fieldPermissionClassification === 'SENSITIVE_EMPLOYMENT_INFO')
|
|
271
|
+
) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
`Employee custom field "${props.apiName}" cannot use a sensitive permission classification ` +
|
|
274
|
+
`with fieldReadAccess "ALL_ACCESS".`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
if (
|
|
278
|
+
runtimeProps.collectDuring === 'ONBOARDING' &&
|
|
279
|
+
(runtimeProps.fieldReadAccess === 'ADMIN_ACCESS' || runtimeProps.fieldWriteAccess === 'ADMIN_ACCESS')
|
|
280
|
+
) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`Employee onboarding custom field "${props.apiName}" must grant the employee read and write access.`,
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
176
286
|
this._fieldId = props.fieldId ?? generateId('cfv2');
|
|
177
287
|
this.props = {
|
|
178
288
|
...props,
|
|
179
289
|
dataType: cloneJson(props.dataType),
|
|
180
|
-
}
|
|
290
|
+
} as CustomFieldProps<ModelRqlName>;
|
|
181
291
|
scope._register(this);
|
|
182
292
|
}
|
|
183
293
|
|
|
@@ -228,8 +338,12 @@ export class CustomField {
|
|
|
228
338
|
displayOrder: (component['display_order'] as number | null | undefined) ?? null,
|
|
229
339
|
};
|
|
230
340
|
if (typeof formula === 'string') {
|
|
341
|
+
if (common.fieldWriteAccess != null && common.fieldWriteAccess !== 'NO_ACCESS') {
|
|
342
|
+
throw new TypeError(`Formula CUSTOM_FIELD_V2 field_write_access must be NO_ACCESS.`);
|
|
343
|
+
}
|
|
231
344
|
return new CustomField(scope, {
|
|
232
345
|
...common,
|
|
346
|
+
fieldWriteAccess: 'NO_ACCESS',
|
|
233
347
|
rqlDefinitionFormula: formula,
|
|
234
348
|
collectDuring: null,
|
|
235
349
|
required: null,
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { generateId } from './_helpers';
|
|
2
|
+
import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
|
|
3
|
+
import type { ManifestComponentDeletion, ManifestScope } from './manifest-builder';
|
|
4
|
+
import { requireStringComponentField } from './_existing-component-fields';
|
|
5
|
+
|
|
6
|
+
export type CustomSkillStatus = 'active' | 'inactive';
|
|
7
|
+
export type CustomSkillSourceType = 'user' | 'company';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Initialization properties for {@link CustomSkill}.
|
|
11
|
+
*/
|
|
12
|
+
export interface CustomSkillProps {
|
|
13
|
+
/**
|
|
14
|
+
* Source-side identifier for this Custom Skill.
|
|
15
|
+
*
|
|
16
|
+
* For a new skill, omit this field and the SDK generates a temporary handle
|
|
17
|
+
* that Composer maps to the skill's generated database UUID during deploy.
|
|
18
|
+
*
|
|
19
|
+
* For an existing skill, use the `source_skill_id` loaded from component
|
|
20
|
+
* search/extraction.
|
|
21
|
+
*
|
|
22
|
+
* Optional. Auto-generated when omitted. @default generateId('skill')
|
|
23
|
+
*/
|
|
24
|
+
sourceSkillId?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Display name shown in Rippling AI.
|
|
27
|
+
*
|
|
28
|
+
* Required.
|
|
29
|
+
*/
|
|
30
|
+
name: string;
|
|
31
|
+
/**
|
|
32
|
+
* Description used to explain when the skill applies.
|
|
33
|
+
*
|
|
34
|
+
* Required. Use `null` to clear this field when updating an existing skill.
|
|
35
|
+
*/
|
|
36
|
+
description: string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Markdown instruction content for the skill.
|
|
39
|
+
*
|
|
40
|
+
* Required.
|
|
41
|
+
*/
|
|
42
|
+
content: string;
|
|
43
|
+
/**
|
|
44
|
+
* Optional folder path for organizing skills. Use `null` to clear this field
|
|
45
|
+
* when updating an existing skill.
|
|
46
|
+
*/
|
|
47
|
+
path?: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Whether the skill is active or inactive.
|
|
50
|
+
*
|
|
51
|
+
* Required.
|
|
52
|
+
*/
|
|
53
|
+
status: CustomSkillStatus;
|
|
54
|
+
/**
|
|
55
|
+
* Skill visibility. `user` creates a personal skill; `company` creates a
|
|
56
|
+
* company skill.
|
|
57
|
+
*
|
|
58
|
+
* Optional create-time visibility. Do not set when updating an existing
|
|
59
|
+
* skill; use `CustomSkill.loadFromExisting(...)` so the extracted value can
|
|
60
|
+
* round-trip unchanged.
|
|
61
|
+
*/
|
|
62
|
+
sourceType?: CustomSkillSourceType;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Defines a Rippling AI Custom Skill and registers it with the manifest.
|
|
67
|
+
*/
|
|
68
|
+
export class CustomSkill {
|
|
69
|
+
static readonly componentType = 'CUSTOM_SKILL' as const;
|
|
70
|
+
|
|
71
|
+
static toDeletionIdentifier(sourceSkillId: string): ManifestComponentDeletion {
|
|
72
|
+
return {
|
|
73
|
+
type: CustomSkill.componentType,
|
|
74
|
+
source_skill_id: sourceSkillId,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private readonly _sourceSkillId: string;
|
|
79
|
+
private _name: string;
|
|
80
|
+
private _description: string | null | undefined;
|
|
81
|
+
private _content: string;
|
|
82
|
+
private _path: string | null | undefined;
|
|
83
|
+
private _status: CustomSkillStatus;
|
|
84
|
+
private _sourceType: CustomSkillSourceType | undefined;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param scope - The manifest to register this skill with.
|
|
88
|
+
* @param props - Initialization properties.
|
|
89
|
+
*/
|
|
90
|
+
constructor(scope: ManifestScope, props: CustomSkillProps) {
|
|
91
|
+
if (props.sourceSkillId != null && props.sourceType != null) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
'CustomSkill sourceType is create-time only. Omit sourceType when constructing an existing skill; ' +
|
|
94
|
+
'use CustomSkill.loadFromExisting(...) to update extracted skills.',
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
this._sourceSkillId = props.sourceSkillId ?? generateId('skill');
|
|
98
|
+
this._name = props.name;
|
|
99
|
+
this._description = props.description;
|
|
100
|
+
this._content = props.content;
|
|
101
|
+
this._path = props.path;
|
|
102
|
+
this._status = props.status;
|
|
103
|
+
this._sourceType = props.sourceType;
|
|
104
|
+
scope._register(this);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Loads this skill from the active existing-manifest JSON context.
|
|
109
|
+
*/
|
|
110
|
+
static loadFromExisting(sourceSkillId: string, options: ExistingManifestContextOptions = {}): CustomSkill {
|
|
111
|
+
return getExistingManifestContext(options).loadCustomSkill(sourceSkillId);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** @internal Hydrates a custom skill from existing manifest wire JSON. */
|
|
115
|
+
static _fromExistingComponent(scope: ManifestScope, component: Record<string, any>): CustomSkill {
|
|
116
|
+
const props: CustomSkillProps = {
|
|
117
|
+
sourceSkillId: requireStringComponentField(component, 'source_skill_id', CustomSkill.componentType),
|
|
118
|
+
name: requireStringComponentField(component, 'name', CustomSkill.componentType),
|
|
119
|
+
description:
|
|
120
|
+
component['description'] == null ?
|
|
121
|
+
null
|
|
122
|
+
: requireStringComponentField(component, 'description', CustomSkill.componentType),
|
|
123
|
+
content: requireStringComponentField(component, 'content', CustomSkill.componentType),
|
|
124
|
+
status: requireStringComponentField(
|
|
125
|
+
component,
|
|
126
|
+
'status',
|
|
127
|
+
CustomSkill.componentType,
|
|
128
|
+
) as CustomSkillStatus,
|
|
129
|
+
};
|
|
130
|
+
if (typeof component['path'] === 'string') props.path = component['path'];
|
|
131
|
+
if (typeof component['source_type'] === 'string') {
|
|
132
|
+
props.sourceType = component['source_type'] as CustomSkillSourceType;
|
|
133
|
+
}
|
|
134
|
+
const { sourceType, ...loadProps } = props;
|
|
135
|
+
const skill = new CustomSkill(scope, loadProps);
|
|
136
|
+
skill._sourceType = sourceType;
|
|
137
|
+
return skill;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Returns this skill's source-side manifest identifier. New skills use a
|
|
142
|
+
* generated temporary handle; extracted skills use their database UUID.
|
|
143
|
+
*/
|
|
144
|
+
getSourceSkillId(): string {
|
|
145
|
+
return this._sourceSkillId;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Replaces the display name for this skill.
|
|
150
|
+
*/
|
|
151
|
+
setName(name: string): this {
|
|
152
|
+
this._name = name;
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Replaces the description for this skill. Pass `null` to clear it.
|
|
158
|
+
*/
|
|
159
|
+
setDescription(description: string | null): this {
|
|
160
|
+
this._description = description;
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Replaces the plaintext markdown instruction content for this skill.
|
|
166
|
+
*/
|
|
167
|
+
setContent(content: string): this {
|
|
168
|
+
this._content = content;
|
|
169
|
+
return this;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Replaces the optional folder path for this skill. Pass `null` to clear it,
|
|
174
|
+
* or `undefined` to omit it from the serialized manifest.
|
|
175
|
+
*/
|
|
176
|
+
setPath(path: string | null | undefined): this {
|
|
177
|
+
this._path = path;
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Replaces whether this skill is active or inactive.
|
|
183
|
+
*/
|
|
184
|
+
setStatus(status: CustomSkillStatus): this {
|
|
185
|
+
this._status = status;
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Serializes this skill to the wire format consumed by the manifest install endpoint.
|
|
191
|
+
*/
|
|
192
|
+
toDict(): Record<string, any> {
|
|
193
|
+
const component: Record<string, any> = {
|
|
194
|
+
type: CustomSkill.componentType,
|
|
195
|
+
source_skill_id: this._sourceSkillId,
|
|
196
|
+
name: this._name,
|
|
197
|
+
content: this._content,
|
|
198
|
+
status: this._status,
|
|
199
|
+
};
|
|
200
|
+
if (this._description !== undefined) component['description'] = this._description;
|
|
201
|
+
if (this._path !== undefined) component['path'] = this._path;
|
|
202
|
+
if (this._sourceType != null) component['source_type'] = this._sourceType;
|
|
203
|
+
return component;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { App } from './app';
|
|
2
|
+
import { Agent } from './agent';
|
|
2
3
|
import { Category } from './category';
|
|
3
4
|
import { CustomField } from './custom-field';
|
|
4
5
|
import { CustomFieldSection } from './custom-field-section';
|
|
@@ -6,6 +7,7 @@ import { CustomObject } from './custom-object';
|
|
|
6
7
|
import { CustomObjectAction } from './custom-object-action';
|
|
7
8
|
import { CustomObjectFieldSection } from './custom-object-field-section';
|
|
8
9
|
import { CustomObjectPageLayout } from './custom-object-page-layout';
|
|
10
|
+
import { CustomSkill } from './custom-skill';
|
|
9
11
|
import { Field } from './field';
|
|
10
12
|
import { ListViewDef } from './list-view';
|
|
11
13
|
import { ManifestBuilder, type ManifestComponent } from './manifest-builder';
|
|
@@ -85,6 +87,7 @@ function componentLabel(component: Record<string, any>): string {
|
|
|
85
87
|
component['rule_id'] ??
|
|
86
88
|
component['flow_id'] ??
|
|
87
89
|
component['sdui_page_id'] ??
|
|
90
|
+
component['source_skill_id'] ??
|
|
88
91
|
component['field_api_name'] ??
|
|
89
92
|
component['section_id'] ??
|
|
90
93
|
'unknown';
|
|
@@ -305,6 +308,15 @@ export class ExistingManifestContext {
|
|
|
305
308
|
return this.loadFunctionComponent(component);
|
|
306
309
|
}
|
|
307
310
|
|
|
311
|
+
loadCustomSkill(sourceSkillId: string): CustomSkill {
|
|
312
|
+
const component = this.findUnique(
|
|
313
|
+
'CUSTOM_SKILL',
|
|
314
|
+
(candidate) => candidate['source_skill_id'] === sourceSkillId,
|
|
315
|
+
`CUSTOM_SKILL ${sourceSkillId}`,
|
|
316
|
+
);
|
|
317
|
+
return this.loadCustomSkillComponent(component);
|
|
318
|
+
}
|
|
319
|
+
|
|
308
320
|
loadSduiPage(sduiPageId: string): SduiPage {
|
|
309
321
|
const component = this.findUnique(
|
|
310
322
|
'SDUI_PAGE',
|
|
@@ -323,8 +335,19 @@ export class ExistingManifestContext {
|
|
|
323
335
|
return this.loadAppComponent(component);
|
|
324
336
|
}
|
|
325
337
|
|
|
338
|
+
loadAgent(apiName: string): Agent {
|
|
339
|
+
const component = this.findUnique(
|
|
340
|
+
'AGENT',
|
|
341
|
+
(candidate) => candidate['api_name'] === apiName,
|
|
342
|
+
`AGENT ${apiName}`,
|
|
343
|
+
);
|
|
344
|
+
return this.loadAgentComponent(component);
|
|
345
|
+
}
|
|
346
|
+
|
|
326
347
|
private loadComponent(component: Record<string, any>): unknown {
|
|
327
348
|
switch (component['type']) {
|
|
349
|
+
case 'AGENT':
|
|
350
|
+
return this.loadAgentComponent(component);
|
|
328
351
|
case 'CUSTOM_CATEGORY':
|
|
329
352
|
return this.loadCategoryComponent(component);
|
|
330
353
|
case 'CUSTOM_OBJECT':
|
|
@@ -347,6 +370,8 @@ export class ExistingManifestContext {
|
|
|
347
370
|
return this.loadValidationComponent(component);
|
|
348
371
|
case 'CUSTOM_OBJECT_RECORD_TRIGGERED_FLOW':
|
|
349
372
|
return this.loadRuleComponent(component);
|
|
373
|
+
case 'CUSTOM_SKILL':
|
|
374
|
+
return this.loadCustomSkillComponent(component);
|
|
350
375
|
case 'FUNCTION':
|
|
351
376
|
return this.loadFunctionComponent(component);
|
|
352
377
|
case 'SDUI_PAGE':
|
|
@@ -538,6 +563,18 @@ export class ExistingManifestContext {
|
|
|
538
563
|
);
|
|
539
564
|
}
|
|
540
565
|
|
|
566
|
+
private loadCustomSkillComponent(component: Record<string, any>): CustomSkill {
|
|
567
|
+
const sourceSkillId = requireStringComponentField(
|
|
568
|
+
component,
|
|
569
|
+
'source_skill_id',
|
|
570
|
+
CustomSkill.componentType,
|
|
571
|
+
);
|
|
572
|
+
const cacheKey = this.cacheKey('CUSTOM_SKILL', sourceSkillId);
|
|
573
|
+
return this.getOrLoad(cacheKey, () =>
|
|
574
|
+
CustomSkill._fromExistingComponent(this.getManifestBuilder(), component),
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
541
578
|
private loadSduiPageComponent(component: Record<string, any>): SduiPage {
|
|
542
579
|
const sduiPageId = requireStringComponentField(component, 'sdui_page_id', SduiPage.componentType);
|
|
543
580
|
const cacheKey = this.cacheKey('SDUI_PAGE', sduiPageId);
|
|
@@ -557,6 +594,16 @@ export class ExistingManifestContext {
|
|
|
557
594
|
});
|
|
558
595
|
}
|
|
559
596
|
|
|
597
|
+
private loadAgentComponent(component: Record<string, any>): Agent {
|
|
598
|
+
const apiName = requireStringComponentField(component, 'api_name', Agent.componentType);
|
|
599
|
+
const cacheKey = this.cacheKey('AGENT', apiName);
|
|
600
|
+
return this.getOrLoad(cacheKey, () =>
|
|
601
|
+
Agent._fromExistingComponent(this.getManifestBuilder(), component, (sourceSkillId) =>
|
|
602
|
+
this.loadRequiredCustomSkillForAgent(sourceSkillId, apiName),
|
|
603
|
+
),
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
|
|
560
607
|
private loadRawComponent(component: Record<string, any>): ExistingRawComponent {
|
|
561
608
|
const index = this.componentIndexes.get(component) ?? -1;
|
|
562
609
|
const cacheKey = this.cacheKey('RAW', `${index}:${componentLabel(component)}`);
|
|
@@ -648,6 +695,20 @@ export class ExistingManifestContext {
|
|
|
648
695
|
return this.loadFunctionComponent(functionComponent);
|
|
649
696
|
}
|
|
650
697
|
|
|
698
|
+
private loadRequiredCustomSkillForAgent(sourceSkillId: string, agentApiName: string): CustomSkill {
|
|
699
|
+
const skillComponent = this.ofType('CUSTOM_SKILL').find(
|
|
700
|
+
(candidate) => candidate['source_skill_id'] === sourceSkillId,
|
|
701
|
+
);
|
|
702
|
+
if (skillComponent == null) {
|
|
703
|
+
throw new Error(
|
|
704
|
+
`AGENT ${agentApiName} references CUSTOM_SKILL ${sourceSkillId}, ` +
|
|
705
|
+
'but that custom skill component is not present. Pass the full existing component extraction ' +
|
|
706
|
+
'to ManifestBuilder.loadFromExistingJson(...).',
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
return this.loadCustomSkillComponent(skillComponent);
|
|
710
|
+
}
|
|
711
|
+
|
|
651
712
|
private loadSyntheticFieldReference(customObjectApiName: string, fieldApiName: string): Field {
|
|
652
713
|
const cacheKey = this.cacheKey('CUSTOM_OBJECT_FIELD_REF', `${customObjectApiName}.${fieldApiName}`);
|
|
653
714
|
return this.getOrLoad(cacheKey, () => Field._syntheticReference(customObjectApiName, fieldApiName));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Manifest builder public API (hand-written, not Stainless-generated). */
|
|
2
2
|
|
|
3
|
+
export { Agent, type AgentIdentityMode, type AgentProps, type AgentSourceFile } from './agent';
|
|
4
|
+
|
|
3
5
|
export {
|
|
4
6
|
generateId,
|
|
5
7
|
type EdgeType,
|
|
@@ -25,15 +27,24 @@ export {
|
|
|
25
27
|
CustomField,
|
|
26
28
|
CustomField as CustomFieldV2,
|
|
27
29
|
type CustomFieldApiName,
|
|
30
|
+
type CustomFieldBaseProps,
|
|
28
31
|
type CustomFieldCollectionTiming,
|
|
29
32
|
type CustomFieldDataType,
|
|
30
33
|
type CustomFieldDefaultValue,
|
|
31
34
|
type CustomFieldPermissionClassification,
|
|
35
|
+
type CustomFieldPermissionProps,
|
|
32
36
|
type CustomFieldProps,
|
|
33
37
|
type CustomFieldReadAccess,
|
|
34
38
|
type CustomFieldType,
|
|
35
39
|
type CustomFieldUniqueIDCharacterType,
|
|
36
40
|
type CustomFieldWriteAccess,
|
|
41
|
+
type EmployeeCustomFieldPermissionProps,
|
|
42
|
+
type EmployeeCustomFieldProps,
|
|
43
|
+
type EmployeeFormulaCustomFieldProps,
|
|
44
|
+
type EmployeeUserInputCustomFieldProps,
|
|
45
|
+
type FormulaCustomFieldProps,
|
|
46
|
+
type NonEmployeeCustomFieldPermissionProps,
|
|
47
|
+
type UserInputCustomFieldProps,
|
|
37
48
|
} from './custom-field';
|
|
38
49
|
|
|
39
50
|
export { CustomFieldSection, type CustomFieldSectionProps } from './custom-field-section';
|
|
@@ -49,6 +60,13 @@ export {
|
|
|
49
60
|
type IconConfig,
|
|
50
61
|
} from './custom-object';
|
|
51
62
|
|
|
63
|
+
export {
|
|
64
|
+
CustomSkill,
|
|
65
|
+
type CustomSkillProps,
|
|
66
|
+
type CustomSkillSourceType,
|
|
67
|
+
type CustomSkillStatus,
|
|
68
|
+
} from './custom-skill';
|
|
69
|
+
|
|
52
70
|
export {
|
|
53
71
|
CustomObjectFieldSection,
|
|
54
72
|
type CustomObjectFieldSectionLoadFromExistingOptions,
|
|
@@ -14,6 +14,7 @@ export interface ManifestComponent {
|
|
|
14
14
|
* Wire-level component types supported by the manifest builder.
|
|
15
15
|
*/
|
|
16
16
|
export type ManifestComponentType =
|
|
17
|
+
| 'AGENT'
|
|
17
18
|
| 'CUSTOM_APP'
|
|
18
19
|
| 'CUSTOM_CATEGORY'
|
|
19
20
|
| 'CUSTOM_FIELD_SECTION'
|
|
@@ -26,6 +27,7 @@ export type ManifestComponentType =
|
|
|
26
27
|
| 'CUSTOM_OBJECT_PAGE_LAYOUT'
|
|
27
28
|
| 'CUSTOM_OBJECT_RECORD_TRIGGERED_FLOW'
|
|
28
29
|
| 'CUSTOM_OBJECT_VALIDATION_RULE'
|
|
30
|
+
| 'CUSTOM_SKILL'
|
|
29
31
|
| 'FUNCTION'
|
|
30
32
|
| 'SDUI_PAGE'
|
|
31
33
|
| 'WORKFLOW_DEFINITION';
|
package/src/resources/index.ts
CHANGED
|
@@ -26,9 +26,9 @@ export interface LeaveProgramEvaluationCreateResponse {
|
|
|
26
26
|
leave_plan: unknown;
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Structured evidence gaps reported by evaluated eligibility rules.
|
|
30
30
|
*/
|
|
31
|
-
missing_evidence: Array<
|
|
31
|
+
missing_evidence: Array<LeaveProgramEvaluationCreateResponse.MissingEvidence>;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Per-program rule outputs in evaluation order.
|
|
@@ -36,6 +36,30 @@ export interface LeaveProgramEvaluationCreateResponse {
|
|
|
36
36
|
program_results: Array<unknown>;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export namespace LeaveProgramEvaluationCreateResponse {
|
|
40
|
+
export interface MissingEvidence {
|
|
41
|
+
/**
|
|
42
|
+
* Expected answer type for this evidence key.
|
|
43
|
+
*/
|
|
44
|
+
answer_type: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Stable evidence key that can be supplied in supplemental_evidence.
|
|
48
|
+
*/
|
|
49
|
+
key: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Human-readable label for the missing evidence.
|
|
53
|
+
*/
|
|
54
|
+
label: string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Leave program codes that reported this missing evidence.
|
|
58
|
+
*/
|
|
59
|
+
program_codes: Array<string>;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
export interface LeaveProgramEvaluationCreateParams {
|
|
40
64
|
/**
|
|
41
65
|
* Requested leave start date.
|
|
@@ -63,6 +87,12 @@ export interface LeaveProgramEvaluationCreateParams {
|
|
|
63
87
|
*/
|
|
64
88
|
child_entered_family_date?: string;
|
|
65
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Demo/test-company only evidence overrides for exercising eligibility scenarios
|
|
92
|
+
* when the role's real data would not qualify.
|
|
93
|
+
*/
|
|
94
|
+
evidence_override?: unknown;
|
|
95
|
+
|
|
66
96
|
/**
|
|
67
97
|
* Optional parental leave relationship type for parental leave programs.
|
|
68
98
|
*/
|
|
@@ -78,6 +108,12 @@ export interface LeaveProgramEvaluationCreateParams {
|
|
|
78
108
|
* program runs in dependency order.
|
|
79
109
|
*/
|
|
80
110
|
program_codes?: Array<string>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Answers for evidence keys returned in missing_evidence. These answers only fill
|
|
114
|
+
* facts that the evaluation reported as missing.
|
|
115
|
+
*/
|
|
116
|
+
supplemental_evidence?: unknown;
|
|
81
117
|
}
|
|
82
118
|
|
|
83
119
|
export declare namespace LeaveProgramEvaluations {
|