Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { z } from 'zod';
export const SkillMetadata = z
.object({
// Empty for now - reserved for user-defined custom data
// State management fields have been moved to proper columns
})
.strict();
export const Skill = z.object({
id: z.uuid(),
agent_id: z.uuid(),
/** Name of the skill. Unique within the agent. */
name: z.string(),
/** Description of the skill. This will be used by Super Agents to automatically optimize the skill. */
description: z.string(),
/** Internal metadata for the skill. Reserved for user-defined custom data. */
metadata: SkillMetadata,
/** Whether to optimize the skill. */
optimize: z.boolean(),
/** Number of configurations for the skill. */
configuration_count: z.int(),
/** Recompute the centroid of the cluster every N requests
* so that they can better represent the last N requests.
*/
clustering_interval: z.int(),
/** Minimum number of requests per arm in a configuration (cluster)
* to trigger reflection.
* This is to ensure that the arms for the cluster have convergence. */
reflection_min_requests_per_arm: z.int(),
/** Temperature parameter for Thompson Sampling exploration.
* Controls the exploration/exploitation tradeoff:
* - 1.0: Standard Thompson Sampling (balanced)
* - > 1.0: More exploration (takes more risks, tries suboptimal arms more often)
* - < 1.0: More exploitation (sticks to known good arms)
* Recommended range: 0.5 to 3.0 */
exploration_temperature: z.number().min(0.1).max(10.0),
/** Timestamp when clustering was last performed for this skill */
last_clustering_at: z.iso.datetime({ offset: true }).nullable(),
/** Unix timestamp of the most recent log used in the last clustering batch.
* We will query the logs from this timestamp to the current time to find the most recent logs. */
last_clustering_log_start_time: z.number().nullable(),
/** The timestamp when evaluations were first regenerated with real examples.
* This happens after the first 5 requests to ensure evaluations align with actual usage. */
evaluations_regenerated_at: z.iso.datetime({ offset: true }).nullable(),
/** Lock timestamp to prevent concurrent evaluation regeneration across edge workers.
* If set and recent (< 5 minutes old), regeneration is in progress. */
evaluation_lock_acquired_at: z.iso.datetime({ offset: true }).nullable(),
/** Total number of requests for this skill (never resets, for lifetime observability) */
total_requests: z.number().min(0),
/** List of allowed Jinja-style template variables that can be used in system prompts.
* These variables will be auto-populated at runtime and shown to the reflector AI.
* Example: ['datetime', 'user_timezone'] */
allowed_template_variables: z.array(z.string()),
created_at: z.iso.datetime({ offset: true }),
updated_at: z.iso.datetime({ offset: true }),
});
export type Skill = z.infer<typeof Skill>;
export const SkillQueryParams = z
.object({
id: z.uuid().optional(),
agent_id: z.uuid().optional(),
name: z
.string()
.regex(/^[a-z0-9_-]+$/, {
message:
'Name must only contain lowercase letters, numbers, underscores, and hyphens',
})
.min(3)
.max(100)
.optional(),
optimize: z.boolean().optional(),
limit: z.coerce.number().int().positive().optional(),
offset: z.coerce.number().int().min(0).optional(),
})
.strict();
export type SkillQueryParams = z.infer<typeof SkillQueryParams>;
export const SkillCreateParams = z
.object({
agent_id: z.uuid(),
name: z
.string()
.min(3)
.max(100)
.regex(/^[a-z0-9_-]+$/, {
message:
'Name must only contain lowercase letters, numbers, underscores, and hyphens',
}),
description: z.string().min(25).max(10000),
metadata: SkillMetadata,
optimize: z.boolean(),
configuration_count: z.int().min(1).max(25).default(3),
clustering_interval: z.int().min(1).max(1000).default(15),
reflection_min_requests_per_arm: z.int().min(1).max(1000).default(3),
exploration_temperature: z.number().min(0.1).max(10.0).default(3.0),
allowed_template_variables: z.array(z.string()).optional().default([]),
})
.strict();
export type SkillCreateParams = z.infer<typeof SkillCreateParams>;
export const SkillUpdateParams = z
.object({
description: z.string().min(25).max(10000).optional(),
metadata: SkillMetadata.optional(),
optimize: z.boolean().optional(),
configuration_count: z.int().min(1).max(25).optional(),
clustering_interval: z.int().min(1).max(1000).optional(),
reflection_min_requests_per_arm: z.int().min(1).max(1000).optional(),
exploration_temperature: z.number().min(0.1).max(10.0).optional(),
allowed_template_variables: z.array(z.string()).optional(),
// State management fields (typically updated by system, not user)
last_clustering_at: z.iso.datetime({ offset: true }).nullable().optional(),
last_clustering_log_start_time: z.number().nullable().optional(),
evaluations_regenerated_at: z.iso
.datetime({ offset: true })
.nullable()
.optional(),
evaluation_lock_acquired_at: z.iso
.datetime({ offset: true })
.nullable()
.optional(),
})
.strict()
.refine(
(data) => {
const updateFields = [
'description',
'metadata',
'optimize',
'configuration_count',
'clustering_interval',
'reflection_min_requests_per_arm',
'exploration_temperature',
'allowed_template_variables',
'last_clustering_at',
'last_clustering_log_start_time',
'evaluations_regenerated_at',
'evaluation_lock_acquired_at',
];
return updateFields.some(
(field) => data[field as keyof typeof data] !== undefined,
);
},
{
message: 'At least one field must be provided for update',
path: [
'description',
'metadata',
'optimize',
'configuration_count',
'clustering_interval',
'reflection_min_requests_per_arm',
'exploration_temperature',
'last_clustering_at',
'last_clustering_log_start_time',
'evaluations_regenerated_at',
'evaluation_lock_acquired_at',
],
},
);
export type SkillUpdateParams = z.infer<typeof SkillUpdateParams>;
|