@apteva/apteva-kit 0.1.124 → 0.1.126

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/index.mjs CHANGED
@@ -735,36 +735,36 @@ function parseWidgetsFromText(text) {
735
735
  // src/utils/widget-context.ts
736
736
  var WIDGET_DEFINITIONS = {
737
737
  card: {
738
- schema: "title, description?, image?, footer?, actions?: [{type, label}]",
738
+ schema: "title, description?, image?(url), footer?, actions?: [{type, label}]",
739
739
  example: '@ui:card[{"title": "Summary", "description": "Details here"}]'
740
740
  },
741
741
  list: {
742
- schema: "items: [{id, title, subtitle?, description?, image?, metadata?: {any extra data}}], actions?: [{type, label}] - metadata is sent as action payload when clicked",
742
+ schema: "items: [{id, title, subtitle?, description?, image?(url), metadata?: {\u2026}}], actions?: [{type, label}]",
743
743
  example: '@ui:list[{"items": [{"id": "1", "title": "Item", "subtitle": "Info", "metadata": {"key": "value"}}]}]'
744
744
  },
745
745
  button_group: {
746
- schema: "buttons: [{id, label, variant?}] - Use for standalone buttons only, NOT for form submits",
746
+ schema: 'buttons: [{id, label, variant?: "default"|"primary"|"danger"}]',
747
747
  example: '@ui:button_group[{"buttons": [{"id": "ok", "label": "OK"}]}]'
748
748
  },
749
749
  form: {
750
- schema: "title?, fields: [{name, type: text|password|number|select|checkbox|textarea|date, label, required?, placeholder?, options?}], actions: [{type, label}] - Button is built-in via actions, do NOT add separate button",
751
- example: '@ui:form[{"title": "Settings", "fields": [{"name": "apiKey", "type": "password", "label": "API Key", "required": true}], "actions": [{"type": "save", "label": "Save"}]}]'
750
+ schema: 'title?, fields: [{name, type: "text"|"password"|"number"|"select"|"checkbox"|"textarea"|"date", label, required?, placeholder?, options?: [{label, value}]}], actions: [{type, label}]',
751
+ example: '@ui:form[{"title": "Settings", "fields": [{"name": "key", "type": "password", "label": "API Key", "required": true}], "actions": [{"type": "save", "label": "Save"}]}]'
752
752
  },
753
753
  table: {
754
- schema: "columns: [{key, label}], rows: [...], striped?, compact?",
755
- example: '@ui:table[{"columns": [{"key": "name", "label": "Name"}], "rows": [{"name": "A"}]}]'
754
+ schema: "columns: [{key, label}], rows: [{key: value, \u2026}], striped?, compact?",
755
+ example: '@ui:table[{"columns": [{"key": "name", "label": "Name"}], "rows": [{"name": "Alice"}]}]'
756
756
  },
757
757
  image: {
758
- schema: "src, alt, caption?",
759
- example: '@ui:image[{"src": "url", "alt": "desc"}]'
758
+ schema: "src(url), alt, caption?",
759
+ example: '@ui:image[{"src": "https://example.com/img.png", "alt": "Photo"}]'
760
760
  },
761
761
  chart: {
762
- schema: "chartType: line|bar|pie, data: {labels, datasets}",
763
- example: '@ui:chart[{"chartType": "bar", "data": {"labels": ["A"], "datasets": [{"label": "X", "data": [10]}]}}]'
762
+ schema: 'chartType: "line"|"bar"|"pie", data: {labels: [...], datasets: [{label, data: [numbers]}]}',
763
+ example: '@ui:chart[{"chartType": "bar", "data": {"labels": ["Q1", "Q2"], "datasets": [{"label": "Revenue", "data": [100, 150]}]}}]'
764
764
  },
765
765
  flow: {
766
- schema: "title, subtitle?, icon?: research|schedule|analyze|deploy|recurring|automation|data, steps: [{id, label, type?, color?: blue|purple|cyan|amber|emerald|rose|indigo|orange, status?: pending|active|completed|error|skipped}] - Horizontal pipeline. Use @label for agents. Types auto-detected from label.",
767
- example: '@ui:flow[{"title": "Deploy Pipeline", "icon": "deploy", "steps": [{"id": "1", "label": "Test", "color": "cyan"}, {"id": "2", "label": "Build", "color": "amber"}, {"id": "3", "label": "Deploy", "color": "rose"}]}]'
766
+ schema: 'title, subtitle?, icon?: "research"|"schedule"|"analyze"|"deploy"|"recurring"|"automation"|"data", steps: [{id, label, color?: "blue"|"purple"|"cyan"|"amber"|"emerald"|"rose"|"indigo"|"orange", status?: "pending"|"active"|"completed"|"error"|"skipped"}]',
767
+ example: '@ui:flow[{"title": "Pipeline", "steps": [{"id": "1", "label": "Test", "color": "cyan"}, {"id": "2", "label": "Deploy", "color": "rose"}]}]'
768
768
  }
769
769
  };
770
770
  var ALL_WIDGET_TYPES = Object.keys(WIDGET_DEFINITIONS);
@@ -774,27 +774,54 @@ function generateWidgetContext(enabledWidgets) {
774
774
  const widgets = enabledWidgets || DEFAULT_WIDGET_TYPES;
775
775
  let context = `
776
776
  ## UI Widgets
777
- SYNTAX: @ui:type[{json}] - MUST use SQUARE BRACKETS [] around the JSON object.
778
- CORRECT: @ui:list[{"items": [...]}]
779
- WRONG: @ui:list{"items": [...]} (missing square brackets)
777
+
778
+ You can render interactive UI widgets inline in your responses. Use them when structured display is clearer than plain text (showing data, forms, actions, images). You may include normal text before or after a widget.
779
+
780
+ **Syntax:** \`@ui:type[{json}]\` \u2014 the JSON object MUST be wrapped in square brackets \`[]\`.
781
+
782
+ Example:
783
+ @ui:list[{"items": [{"id": "1", "title": "First item"}]}]
784
+
785
+ Do NOT wrap widgets in code blocks or backticks. Write them directly in your response text.
786
+
787
+ ### Available widgets
780
788
 
781
789
  `;
782
790
  for (const type of widgets) {
783
791
  const def = WIDGET_DEFINITIONS[type];
784
792
  if (!def) continue;
785
- context += `${type}: ${def.schema} | ${def.example}
793
+ context += `**${type}** \u2014 ${def.schema}
794
+ `;
795
+ context += ` ${def.example}
796
+
786
797
  `;
787
798
  }
788
- context += `
789
- Per-item "metadata" is sent as payload on action click.
799
+ context += `### Notes
800
+ - **actions**: the \`type\` field is a custom string you choose (e.g. "edit", "delete", "submit"). It is returned to the app when the user clicks the button.
801
+ - **metadata** on list items: any extra data attached to an item. Returned as the action payload when the user clicks that item.
802
+ - **form**: buttons are defined in \`actions\`, do NOT add a separate button_group for form submission.
803
+ - **select fields**: \`options\` is an array of \`{label, value}\` objects.
790
804
  `;
791
805
  return context;
792
806
  }
793
807
  function generateCompactWidgetContext(enabledWidgets) {
794
808
  const widgets = enabledWidgets || DEFAULT_WIDGET_TYPES;
795
- return `
796
- Widgets: @ui:type[{json}] - MUST use square brackets []. Example: @ui:list[{"items": [...]}]. Types: ${widgets.join(", ")}. Per-item "metadata" is sent as action payload.
809
+ let context = `
810
+ ## UI Widgets
811
+ Render widgets inline: \`@ui:type[{json}]\` (square brackets required, no code blocks).
812
+ Use when structured display is clearer than plain text. Normal text can surround widgets.
813
+
814
+ `;
815
+ for (const type of widgets) {
816
+ const def = WIDGET_DEFINITIONS[type];
817
+ if (!def) continue;
818
+ context += `**${type}**: ${def.schema}
797
819
  `;
820
+ }
821
+ context += `
822
+ actions.type = custom string returned on click. list metadata = payload on item click. form buttons go in actions, not button_group.
823
+ `;
824
+ return context;
798
825
  }
799
826
 
800
827
  // src/utils/interface-parser.ts
@@ -3183,7 +3210,7 @@ function WelcomeScreen({
3183
3210
  const hasPrompts = normalizedPrompts.length > 0;
3184
3211
  const hasHeader = title || subtitle || icon;
3185
3212
  if (!hasHeader && !hasPrompts) {
3186
- return /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-center h-full !text-neutral-500 dark:!text-neutral-400", children: /* @__PURE__ */ jsxs16("div", { className: "text-center space-y-2", children: [
3213
+ return /* @__PURE__ */ jsx21("div", { className: "apteva-welcome-empty flex items-center justify-center h-full", children: /* @__PURE__ */ jsxs16("div", { className: "text-center space-y-2", children: [
3187
3214
  /* @__PURE__ */ jsx21("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx21(DefaultIcon, {}) }),
3188
3215
  /* @__PURE__ */ jsx21("p", { className: "text-sm", children: "No messages yet. Start a conversation!" })
3189
3216
  ] }) });
@@ -3191,27 +3218,23 @@ function WelcomeScreen({
3191
3218
  if (variant === "minimal") {
3192
3219
  return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col h-full px-4 py-4", children: [
3193
3220
  hasHeader && /* @__PURE__ */ jsxs16("div", { className: "mb-4", children: [
3194
- title && /* @__PURE__ */ jsx21("h2", { className: "text-lg font-semibold !text-neutral-900 dark:!text-white", children: title }),
3195
- subtitle && /* @__PURE__ */ jsx21("p", { className: "text-sm !text-neutral-500 dark:!text-neutral-400 mt-1", children: subtitle })
3221
+ title && /* @__PURE__ */ jsx21("h2", { className: "apteva-welcome-title text-lg font-semibold", children: title }),
3222
+ subtitle && /* @__PURE__ */ jsx21("p", { className: "apteva-welcome-subtitle text-sm mt-1", children: subtitle })
3196
3223
  ] }),
3197
3224
  hasPrompts && /* @__PURE__ */ jsx21("div", { className: "flex-1 space-y-2", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ jsx21(
3198
3225
  "button",
3199
3226
  {
3200
3227
  onClick: () => onPromptClick(prompt.text),
3201
3228
  className: cn(
3202
- "w-full text-left px-4 py-3 rounded-xl",
3203
- "bg-neutral-50 dark:bg-neutral-800/50",
3204
- "border border-neutral-200 dark:border-neutral-700",
3205
- "hover:bg-neutral-100 dark:hover:bg-neutral-800",
3206
- "hover:border-neutral-300 dark:hover:border-neutral-600",
3207
- "transition-all duration-200",
3229
+ "apteva-prompt-card w-full text-left px-4 py-3 rounded-xl",
3230
+ "border transition-all duration-200",
3208
3231
  "group"
3209
3232
  ),
3210
3233
  children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-3", children: [
3211
- /* @__PURE__ */ jsx21("div", { className: "flex-shrink-0 !text-neutral-400 dark:!text-neutral-500 group-hover:!text-blue-500 dark:group-hover:!text-blue-400 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx21(ArrowIcon, {}) }),
3234
+ /* @__PURE__ */ jsx21("div", { className: "apteva-prompt-icon flex-shrink-0 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx21(ArrowIcon, {}) }),
3212
3235
  /* @__PURE__ */ jsxs16("div", { className: "flex-1 min-w-0", children: [
3213
- /* @__PURE__ */ jsx21("p", { className: "text-sm font-medium !text-neutral-900 dark:!text-white truncate", children: prompt.text }),
3214
- prompt.description && /* @__PURE__ */ jsx21("p", { className: "text-xs !text-neutral-500 dark:!text-neutral-400 mt-0.5 truncate", children: prompt.description })
3236
+ /* @__PURE__ */ jsx21("p", { className: "apteva-prompt-text text-sm font-medium truncate", children: prompt.text }),
3237
+ prompt.description && /* @__PURE__ */ jsx21("p", { className: "apteva-prompt-desc text-xs mt-0.5 truncate", children: prompt.description })
3215
3238
  ] })
3216
3239
  ] })
3217
3240
  },
@@ -3221,9 +3244,9 @@ function WelcomeScreen({
3221
3244
  }
3222
3245
  return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col items-center justify-center h-full px-4 py-6 sm:py-8", children: [
3223
3246
  /* @__PURE__ */ jsxs16("div", { className: "text-center mb-6 sm:mb-8 max-w-md", children: [
3224
- /* @__PURE__ */ jsx21("div", { className: "mb-4 !text-neutral-400 dark:!text-neutral-500 flex justify-center", children: icon || /* @__PURE__ */ jsx21(DefaultIcon, {}) }),
3225
- title && /* @__PURE__ */ jsx21("h1", { className: "text-xl sm:text-2xl font-semibold !text-neutral-900 dark:!text-white mb-2", children: title }),
3226
- subtitle && /* @__PURE__ */ jsx21("p", { className: "text-sm sm:text-base !text-neutral-500 dark:!text-neutral-400", children: subtitle })
3247
+ /* @__PURE__ */ jsx21("div", { className: "apteva-welcome-icon mb-4 flex justify-center", children: icon || /* @__PURE__ */ jsx21(DefaultIcon, {}) }),
3248
+ title && /* @__PURE__ */ jsx21("h1", { className: "apteva-welcome-title text-xl sm:text-2xl font-semibold mb-2", children: title }),
3249
+ subtitle && /* @__PURE__ */ jsx21("p", { className: "apteva-welcome-subtitle text-sm sm:text-base", children: subtitle })
3227
3250
  ] }),
3228
3251
  hasPrompts && /* @__PURE__ */ jsxs16("div", { className: "w-full max-w-2xl", children: [
3229
3252
  /* @__PURE__ */ jsx21("div", { className: "sm:hidden space-y-2", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ jsx21(
@@ -3231,26 +3254,22 @@ function WelcomeScreen({
3231
3254
  {
3232
3255
  onClick: () => onPromptClick(prompt.text),
3233
3256
  className: cn(
3234
- "w-full text-left px-4 py-3 rounded-xl",
3235
- "bg-white dark:bg-neutral-800",
3236
- "border border-neutral-200 dark:border-neutral-700",
3237
- "hover:bg-neutral-50 dark:hover:bg-neutral-700",
3238
- "hover:border-blue-300 dark:hover:border-blue-600",
3257
+ "apteva-prompt-card w-full text-left px-4 py-3 rounded-xl",
3258
+ "border transition-all duration-200",
3239
3259
  "active:scale-[0.98]",
3240
- "transition-all duration-200",
3241
3260
  "shadow-sm hover:shadow",
3242
3261
  "group"
3243
3262
  ),
3244
3263
  children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-3", children: [
3245
- /* @__PURE__ */ jsx21("div", { className: "flex-shrink-0 w-8 h-8 rounded-lg bg-neutral-100 dark:bg-neutral-700 flex items-center justify-center !text-neutral-500 dark:!text-neutral-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/30 group-hover:!text-blue-600 dark:group-hover:!text-blue-400 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx21(ArrowIcon, {}) }),
3264
+ /* @__PURE__ */ jsx21("div", { className: "apteva-prompt-icon-box flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center transition-colors", children: prompt.icon || /* @__PURE__ */ jsx21(ArrowIcon, {}) }),
3246
3265
  /* @__PURE__ */ jsxs16("div", { className: "flex-1 min-w-0", children: [
3247
- /* @__PURE__ */ jsx21("p", { className: "text-sm font-medium !text-neutral-900 dark:!text-white", children: prompt.text }),
3248
- prompt.description && /* @__PURE__ */ jsx21("p", { className: "text-xs !text-neutral-500 dark:!text-neutral-400 mt-0.5 line-clamp-1", children: prompt.description })
3266
+ /* @__PURE__ */ jsx21("p", { className: "apteva-prompt-text text-sm font-medium", children: prompt.text }),
3267
+ prompt.description && /* @__PURE__ */ jsx21("p", { className: "apteva-prompt-desc text-xs mt-0.5 line-clamp-1", children: prompt.description })
3249
3268
  ] }),
3250
3269
  /* @__PURE__ */ jsx21(
3251
3270
  "svg",
3252
3271
  {
3253
- className: "w-4 h-4 !text-neutral-400 group-hover:!text-blue-500 transition-colors flex-shrink-0",
3272
+ className: "apteva-prompt-chevron w-4 h-4 transition-colors flex-shrink-0",
3254
3273
  fill: "none",
3255
3274
  stroke: "currentColor",
3256
3275
  viewBox: "0 0 24 24",
@@ -3274,21 +3293,17 @@ function WelcomeScreen({
3274
3293
  {
3275
3294
  onClick: () => onPromptClick(prompt.text),
3276
3295
  className: cn(
3277
- "text-left p-4 rounded-xl",
3278
- "bg-white dark:bg-neutral-800",
3279
- "border border-neutral-200 dark:border-neutral-700",
3280
- "hover:bg-neutral-50 dark:hover:bg-neutral-700",
3281
- "hover:border-blue-300 dark:hover:border-blue-600",
3296
+ "apteva-prompt-card text-left p-4 rounded-xl",
3297
+ "border transition-all duration-200",
3282
3298
  "hover:shadow-md",
3283
3299
  "active:scale-[0.98]",
3284
- "transition-all duration-200",
3285
3300
  "group"
3286
3301
  ),
3287
3302
  children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-3", children: [
3288
- /* @__PURE__ */ jsx21("div", { className: "flex-shrink-0 w-9 h-9 rounded-lg bg-neutral-100 dark:bg-neutral-700 flex items-center justify-center !text-neutral-500 dark:!text-neutral-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/30 group-hover:!text-blue-600 dark:group-hover:!text-blue-400 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx21(ArrowIcon, {}) }),
3303
+ /* @__PURE__ */ jsx21("div", { className: "apteva-prompt-icon-box flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center transition-colors", children: prompt.icon || /* @__PURE__ */ jsx21(ArrowIcon, {}) }),
3289
3304
  /* @__PURE__ */ jsxs16("div", { className: "flex-1 min-w-0", children: [
3290
- /* @__PURE__ */ jsx21("p", { className: "text-sm font-medium !text-neutral-900 dark:!text-white leading-snug", children: prompt.text }),
3291
- prompt.description && /* @__PURE__ */ jsx21("p", { className: "text-xs !text-neutral-500 dark:!text-neutral-400 mt-1 line-clamp-2", children: prompt.description })
3305
+ /* @__PURE__ */ jsx21("p", { className: "apteva-prompt-text text-sm font-medium leading-snug", children: prompt.text }),
3306
+ prompt.description && /* @__PURE__ */ jsx21("p", { className: "apteva-prompt-desc text-xs mt-1 line-clamp-2", children: prompt.description })
3292
3307
  ] })
3293
3308
  ] })
3294
3309
  },