@m6d/cortex-cli 1.8.0 → 1.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m6d/cortex-cli",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Scaffold and operate Cortex servers",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -13,42 +13,22 @@ export const AGENT_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}$/;
13
13
  /** Tool names become `tools.<name>()` sandbox bindings on the server. */
14
14
  export const TOOL_NAME_PATTERN = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
15
15
 
16
- export const PROMPT_VARIABLES = ["userName", "channel", "locale", "utcTime", "timezone"] as const;
17
-
18
16
  /**
19
- * One entry per prompt variable, driving editor autocomplete, validation, and
20
- * runtime substitution alike. Adding a variable = extending the tuple above
21
- * plus one entry here (the compiler enforces the pair); the consumer embedding
22
- * the agent supplies the value in its session/request context under the same
23
- * key. Descriptions are plain English on purpose: variables are code-like
24
- * identifiers shown in an LTR suggestion list, not localized UI copy.
17
+ * A variable the server fills per request: a session value, a request-context
18
+ * value, or one the SDK computes. Declared per agent so the console offers
19
+ * exactly what that agent's server provides, in prompts and as tool input
20
+ * sources alike.
25
21
  */
26
- export const PROMPT_VARIABLE_DEFINITIONS = {
27
- userName: {
28
- description: "Display name of the signed-in user",
29
- example: "Sara",
30
- },
31
- channel: {
32
- description: "Channel the conversation arrived on",
33
- example: "web",
34
- },
35
- locale: {
36
- description: "Resolved locale of the session",
37
- example: "ar",
38
- },
39
- // The server computes utcTime per request (a consumer-supplied value
40
- // still wins); timezone has no server default — only the consumer knows
41
- // the session's zone, so it must arrive via session/request context or
42
- // the placeholder stays literal.
43
- utcTime: {
44
- description: "Current time in UTC (ISO 8601)",
45
- example: "2026-08-16T09:30:00Z",
46
- },
47
- timezone: {
48
- description: "IANA time zone of the session",
49
- example: "Asia/Dubai",
50
- },
51
- } satisfies Record<(typeof PROMPT_VARIABLES)[number], { description: string; example: string }>;
22
+ export const variableDeclarationSchema = z.object({
23
+ name: z
24
+ .string()
25
+ .regex(/^[A-Za-z_$][A-Za-z0-9_$]*$/)
26
+ .max(64),
27
+ description: z.string().max(500),
28
+ example: z.string().max(200),
29
+ /** Computed by the SDK per request (`utcTime`, `locale`); no session value can set it. */
30
+ computed: z.boolean().default(false),
31
+ });
52
32
 
53
33
  export const RUNTIME_ERROR_KINDS = [
54
34
  "timeout",
@@ -68,6 +48,29 @@ export const JSON_SCHEMA_ISSUE_KINDS = ["missing", "unexpected", "type_mismatch"
68
48
 
69
49
  export const agentSlugSchema = z.string().regex(AGENT_SLUG_PATTERN);
70
50
  export const localeSchema = z.enum(["en", "ar"]);
51
+
52
+ /**
53
+ * The widget's landing-page prompt chips, per locale. Every source of them
54
+ * (the Control Center agent row, a server-code override, the capabilities
55
+ * handshake) stores this exact shape, so the widget never sees a blank or
56
+ * unbounded chip whichever source won. Pure validation, no transforms: a
57
+ * value that passes is served verbatim, so each source trims before it
58
+ * stores.
59
+ */
60
+ export const SUGGESTION_LIMITS = { perLocale: 6, chipLength: 200 } as const;
61
+ export const suggestionsSchema = z.record(
62
+ localeSchema,
63
+ z
64
+ .array(
65
+ z
66
+ .string()
67
+ .min(1)
68
+ .max(SUGGESTION_LIMITS.chipLength)
69
+ .refine((chip) => chip === chip.trim(), "chip has surrounding whitespace"),
70
+ )
71
+ .max(SUGGESTION_LIMITS.perLocale),
72
+ );
73
+ export type Suggestions = z.infer<typeof suggestionsSchema>;
71
74
  export const catalogVersionSchema = z.string().regex(/^[0-9a-f]{16}$/);
72
75
 
73
76
  export const sharedShapeSchema = z.object({
@@ -101,6 +104,13 @@ export const toolEmbedSchema = z.object({
101
104
  embedOrigin: z.url(),
102
105
  });
103
106
 
107
+ /**
108
+ * Variables a tool's input reads (`x-source` of kind `variable` on an input
109
+ * property). The server fills those fields from the agent's declared
110
+ * variables at execute time and the model never sees them.
111
+ */
112
+ const boundVariablesSchema = z.array(variableDeclarationSchema.shape.name);
113
+
104
114
  export const toolSignatureSchema = z.object({
105
115
  toolId: z.uuid(),
106
116
  name: z.string().regex(TOOL_NAME_PATTERN),
@@ -110,6 +120,7 @@ export const toolSignatureSchema = z.object({
110
120
  signature: z.string(),
111
121
  score: z.number().nullable(),
112
122
  pinned: z.boolean(),
123
+ variables: boundVariablesSchema,
113
124
  embed: toolEmbedSchema.optional(),
114
125
  /** Client tools only: the published input JSON Schema, verbatim.
115
126
  * Client-executed declarations need a real schema — the rendered
@@ -159,11 +170,22 @@ export const agentRefSchema = z.string().max(128);
159
170
  */
160
171
  export const AGENT_REF_HEADER = "X-CC-Agent-Ref";
161
172
 
173
+ /**
174
+ * The playground operator's stand-in for a test thread's session: a
175
+ * URI-encoded JSON object of declared variable values, sent by cc's
176
+ * playground beside `X-Cortex-Playground` and honoured only when that header
177
+ * verifies. The server stores it as the thread's session on creation, so the
178
+ * customer's `loadSessionData` (which never sees cc-minted tokens) is not
179
+ * needed for prompts and tool sources to have values.
180
+ */
181
+ export const PLAYGROUND_SESSION_HEADER = "X-Cortex-Playground-Session";
182
+
162
183
  /** A sandbox binding a piece of rich text mentions, so the turn can register it before the model reads the text. */
163
184
  export const mentionedToolSchema = z.object({
164
185
  toolId: z.uuid(),
165
186
  name: z.string().regex(TOOL_NAME_PATTERN),
166
187
  readOnly: z.boolean(),
188
+ variables: boundVariablesSchema,
167
189
  });
168
190
 
169
191
  export const skillBodyResponseSchema = z.object({
@@ -252,6 +274,22 @@ export const triggerDeclarationSchema = z.object({
252
274
  secretHash: sha256HexSchema,
253
275
  });
254
276
 
277
+ /**
278
+ * What a server runs for one agent, sent whole at boot in `agent.declare`. An
279
+ * agent exists in the Control Center only through a declaration, and only
280
+ * its declaring server may serve it. Everything the console validates
281
+ * against (variables, code skills, code triggers) is here rather than
282
+ * assumed.
283
+ */
284
+ export const agentDeclarationSchema = z.object({
285
+ slug: agentSlugSchema,
286
+ variables: z.array(variableDeclarationSchema),
287
+ skills: z.array(skillLineSchema),
288
+ triggers: z.array(
289
+ triggerDeclarationSchema.pick({ name: true, description: true, input: true, thread: true }),
290
+ ),
291
+ });
292
+
255
293
  export const triggerFiringResponseSchema = z.discriminatedUnion("outcome", [
256
294
  z.object({
257
295
  firingId: z.uuid(),
@@ -308,7 +346,10 @@ export const triggerAuthResponseSchema = z.discriminatedUnion("ok", [
308
346
  ]);
309
347
 
310
348
  export const runtimeAgentConfigSchema = z.object({
349
+ /** The slug the request used: the agent's own or one of the server's aliases. */
311
350
  agentId: agentSlugSchema,
351
+ /** The agent's own slug, the key of its `agents` entry in server code. Equals `agentId` unless an alias was used. */
352
+ slug: agentSlugSchema,
312
353
  /**
313
354
  * End-user JWT verification for this agent, managed by the agent's owner.
314
355
  * Tokens must be asymmetrically signed (the JWKS URI serves the public
@@ -326,7 +367,8 @@ export const runtimeAgentConfigSchema = z.object({
326
367
  })
327
368
  .optional(),
328
369
  systemPrompt: z.string(),
329
- promptVariables: z.array(z.enum(PROMPT_VARIABLES)),
370
+ /** Every declared variable the published prompt, skills, or triggers reference. */
371
+ promptVariables: z.array(variableDeclarationSchema.shape.name),
330
372
  defaultLocale: localeSchema,
331
373
  /**
332
374
  * Whether end users may upload files to this agent. Operational config
@@ -351,6 +393,8 @@ export const runtimeAgentConfigSchema = z.object({
351
393
  triggers: z.array(triggerDeclarationSchema).default([]),
352
394
  /** Whether end users may message this agent; false makes it headless. */
353
395
  messageTrigger: z.boolean().default(true),
396
+ /** Operational like `messageTrigger`: edited on the agent row without republishing. */
397
+ suggestions: suggestionsSchema,
354
398
  /** Absent from older Control Centers; reports then carry only the slug. */
355
399
  agentRef: agentRefSchema.optional(),
356
400
  catalogVersion: catalogVersionSchema,
@@ -425,6 +469,8 @@ export const executeRequestSchema = z.object({
425
469
  threadId: z.string().max(128).optional(),
426
470
  userId: z.string().max(128).optional(),
427
471
  locale: localeSchema.optional(),
472
+ /** Values of the variables the tool's input reads; only those names travel. */
473
+ variables: z.record(z.string(), z.unknown()).optional(),
428
474
  })
429
475
  .optional(),
430
476
  });
@@ -561,17 +607,13 @@ export const syncEventSchema = z.discriminatedUnion("type", [
561
607
  createdAt: z.iso.datetime(),
562
608
  finishedAt: z.iso.datetime().nullable(),
563
609
  }),
564
- // Every code trigger the server declares, sent whole at boot so cc can
565
- // list them read-only beside its own. Replaces the server's previous
566
- // declaration, so an agent removed from code takes its triggers with it.
610
+ // Everything the server runs, sent whole at boot. Replaces the server's
611
+ // previous declaration, so an agent removed from code leaves cc with its
612
+ // skills and triggers.
567
613
  z.object({
568
- type: z.literal("trigger.declare"),
614
+ type: z.literal("agent.declare"),
569
615
  id: z.uuid(),
570
- triggers: z.array(
571
- triggerDeclarationSchema
572
- .pick({ name: true, description: true, input: true, thread: true })
573
- .extend({ agentSlug: agentSlugSchema }),
574
- ),
616
+ agents: z.array(agentDeclarationSchema),
575
617
  createdAt: z.iso.datetime(),
576
618
  }),
577
619
  ]);
@@ -612,6 +654,8 @@ export type ResolveResponse = z.infer<typeof resolveResponseSchema>;
612
654
  export type SkillLine = z.infer<typeof skillLineSchema>;
613
655
  export type SkillBodyResponse = z.infer<typeof skillBodyResponseSchema>;
614
656
  export type TriggerDeclaration = z.infer<typeof triggerDeclarationSchema>;
657
+ export type AgentDeclaration = z.infer<typeof agentDeclarationSchema>;
658
+ export type VariableDeclaration = z.infer<typeof variableDeclarationSchema>;
615
659
  export type TriggerThreadPolicy = z.infer<typeof triggerThreadPolicySchema>;
616
660
  export type TriggerOutcome = (typeof TRIGGER_OUTCOMES)[number];
617
661
  export type TriggerDropReason = (typeof TRIGGER_DROP_REASONS)[number];
@@ -21,6 +21,9 @@ export const MAX_ATTACHMENTS_PER_MESSAGE = 5;
21
21
 
22
22
  export const ATTACHMENT_STATUSES = ["pending", "described", "failed", "skipped"] as const;
23
23
 
24
+ /** Who put the file in the thread: the user through the composer, or a tool mid-turn. */
25
+ export const ATTACHMENT_ORIGINS = ["upload", "tool"] as const;
26
+
24
27
  export function checkAttachmentPolicy(contentType: string, sizeBytes: number) {
25
28
  if (!ATTACHMENT_MIME_TYPES.some((type) => type === contentType)) return "type";
26
29
  if (sizeBytes > ATTACHMENT_MAX_BYTES) return "size";
@@ -29,12 +32,15 @@ export function checkAttachmentPolicy(contentType: string, sizeBytes: number) {
29
32
 
30
33
  export type AttachmentStatus = (typeof ATTACHMENT_STATUSES)[number];
31
34
 
35
+ export type AttachmentOrigin = (typeof ATTACHMENT_ORIGINS)[number];
36
+
32
37
  export type AttachmentSummary = {
33
38
  id: string;
34
39
  filename: string;
35
40
  contentType: string;
36
41
  sizeBytes: number;
37
42
  status: AttachmentStatus;
43
+ origin: AttachmentOrigin;
38
44
  description?: string;
39
45
  };
40
46
 
@@ -81,6 +87,8 @@ export type ClientToolBinding = {
81
87
  toolId: string;
82
88
  surface: "inline" | "modal";
83
89
  embedOrigin: string;
90
+ /** Variables the initiate call's input reads. */
91
+ variables: string[];
84
92
  };
85
93
 
86
94
  /**
@@ -91,6 +99,8 @@ export type AgentCapabilities = {
91
99
  attachments: boolean;
92
100
  /** False when the agent's `message` trigger is off: the widget hides its composer. */
93
101
  messages: boolean;
102
+ /** Prompt chips on the blank-chat landing per locale, the runtime contract's `suggestionsSchema` shape; clicking one sends it as the first message. */
103
+ suggestions: Record<"en" | "ar", string[]>;
94
104
  };
95
105
 
96
106
  export type MessageMetadata = {