@veltra/ai 1.4.0 → 2.1.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.
Files changed (87) hide show
  1. package/dist/chat/index.d.ts +3 -3
  2. package/dist/chat/transports/index.d.ts +2 -2
  3. package/dist/chat/transports/openai.d.ts +16 -12
  4. package/dist/chat/transports/openai.js +56 -15
  5. package/dist/chat/transports/openai.js.map +1 -1
  6. package/dist/chat/types.d.ts +41 -2
  7. package/dist/chat/use-chat.d.ts +26 -1
  8. package/dist/chat/use-chat.js +132 -13
  9. package/dist/chat/use-chat.js.map +1 -1
  10. package/dist/components/ai-chat/ai-chat.js +222 -41
  11. package/dist/components/ai-chat/ai-chat.js.map +1 -1
  12. package/dist/components/ai-chat/ask-question.js +2 -2
  13. package/dist/components/ai-chat/ask-question.js.map +1 -1
  14. package/dist/components/ai-chat/chat-input.js +81 -44
  15. package/dist/components/ai-chat/chat-input.js.map +1 -1
  16. package/dist/components/ai-chat/di.js.map +1 -1
  17. package/dist/components/ai-chat/message-item.js +101 -23
  18. package/dist/components/ai-chat/message-item.js.map +1 -1
  19. package/dist/components/ai-chat/message-list.js +217 -32
  20. package/dist/components/ai-chat/message-list.js.map +1 -1
  21. package/dist/components/ai-chat/model-picker.js +140 -0
  22. package/dist/components/ai-chat/model-picker.js.map +1 -0
  23. package/dist/components/ai-chat/queue-list.js +70 -0
  24. package/dist/components/ai-chat/queue-list.js.map +1 -0
  25. package/dist/components/ai-chat/side-panel.js +96 -0
  26. package/dist/components/ai-chat/side-panel.js.map +1 -0
  27. package/dist/components/ai-chat/style.d.ts +6 -0
  28. package/dist/components/ai-chat/style.js +6 -0
  29. package/dist/components/ai-chat/style2.css +552 -41
  30. package/dist/components/ai-chat/tool-call.js +61 -27
  31. package/dist/components/ai-chat/tool-call.js.map +1 -1
  32. package/dist/components/ai-orb/ai-orb.js +94 -0
  33. package/dist/components/ai-orb/ai-orb.js.map +1 -0
  34. package/dist/components/ai-orb/orb-renderer.js +411 -0
  35. package/dist/components/ai-orb/orb-renderer.js.map +1 -0
  36. package/dist/components/ai-orb/style.d.ts +1 -0
  37. package/dist/components/ai-orb/style.js +1 -0
  38. package/dist/components/ai-orb/style2.css +23 -0
  39. package/dist/index.d.ts +8 -6
  40. package/dist/index.js +2 -2
  41. package/dist/providers/types.d.ts +47 -0
  42. package/dist/style.js +1 -0
  43. package/dist/tools/ask-question/ask-question.d.ts +2 -17
  44. package/dist/tools/ask-question/index.d.ts +2 -2
  45. package/dist/tools/index.d.ts +3 -2
  46. package/dist/tools/index.js +10 -0
  47. package/dist/tools/index.js.map +1 -0
  48. package/dist/types/ai-chat.d.ts +35 -7
  49. package/dist/types/ai-orb.d.ts +27 -0
  50. package/dist/types/index.d.ts +2 -1
  51. package/package.json +8 -8
  52. package/src/chat/__test__/use-chat.test.ts +295 -9
  53. package/src/chat/transports/__test__/openai.test.ts +317 -0
  54. package/src/chat/transports/openai.ts +88 -26
  55. package/src/chat/types.ts +41 -1
  56. package/src/chat/use-chat.ts +177 -14
  57. package/src/components/ai-chat/__test__/ai-chat.test.ts +690 -12
  58. package/src/components/ai-chat/ai-chat.vue +241 -31
  59. package/src/components/ai-chat/chat-input.vue +78 -31
  60. package/src/components/ai-chat/di.ts +2 -0
  61. package/src/components/ai-chat/message-item.vue +98 -11
  62. package/src/components/ai-chat/message-list.vue +261 -21
  63. package/src/components/ai-chat/model-picker.vue +177 -0
  64. package/src/components/ai-chat/queue-list.vue +63 -0
  65. package/src/components/ai-chat/side-panel.vue +76 -0
  66. package/src/components/ai-chat/style.scss +621 -43
  67. package/src/components/ai-chat/style.ts +6 -0
  68. package/src/components/ai-chat/tool-call.vue +86 -42
  69. package/src/components/ai-orb/__test__/ai-orb.test.ts +251 -0
  70. package/src/components/ai-orb/ai-orb.vue +107 -0
  71. package/src/components/ai-orb/index.ts +1 -0
  72. package/src/components/ai-orb/orb-renderer.ts +505 -0
  73. package/src/components/ai-orb/style.scss +10 -0
  74. package/src/components/ai-orb/style.ts +1 -0
  75. package/src/components/index.ts +1 -0
  76. package/src/index.ts +8 -1
  77. package/src/providers/index.ts +1 -0
  78. package/src/providers/types.ts +46 -0
  79. package/src/style.ts +1 -0
  80. package/src/tools/ask-question/__test__/ask-question.test.ts +4 -4
  81. package/src/tools/index.ts +14 -1
  82. package/src/types/ai-chat.ts +35 -6
  83. package/src/types/ai-orb.ts +27 -0
  84. package/src/types/index.ts +1 -0
  85. package/dist/components/ai-chat/ai-chat.vue.d.ts +0 -36
  86. package/dist/components/ai-chat/index.d.ts +0 -2
  87. package/dist/components/index.d.ts +0 -3
@@ -0,0 +1,96 @@
1
+ import { AiChatDIKey } from "./di.js";
2
+ import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, inject, normalizeClass, openBlock, resolveDynamicComponent, toDisplayString, unref, withCtx } from "vue";
3
+ import { CircleCheckFilled, CircleClose, Close, Loading, WarningFilled } from "@veltra/icons/normal";
4
+ import { UIcon, UScroll } from "@veltra/desktop";
5
+ import { bem } from "@veltra/utils";
6
+ //#region src/components/ai-chat/side-panel.vue
7
+ const _sfc_main = /*@__PURE__*/ defineComponent({
8
+ name: "UAiChatSidePanel",
9
+ __name: "side-panel",
10
+ props: { toolCall: {} },
11
+ emits: ["close"],
12
+ setup(__props, { emit: __emit }) {
13
+ const props = __props;
14
+ const emit = __emit;
15
+ const di = inject(AiChatDIKey);
16
+ const cls = di?.cls ?? bem("ai-chat");
17
+ /** 当前调用对应的工具定义(解析 icon/label/render) */
18
+ const tool = computed(() => di?.tools.value[props.toolCall.name]);
19
+ const STATUS_META = {
20
+ pending: {
21
+ icon: Loading,
22
+ class: "is-active"
23
+ },
24
+ running: {
25
+ icon: Loading,
26
+ class: "is-active"
27
+ },
28
+ "awaiting-confirm": {
29
+ icon: WarningFilled,
30
+ class: "is-warning"
31
+ },
32
+ success: {
33
+ icon: CircleCheckFilled,
34
+ class: "is-success"
35
+ },
36
+ error: {
37
+ icon: CircleClose,
38
+ class: "is-danger"
39
+ },
40
+ rejected: {
41
+ icon: Close,
42
+ class: "is-danger"
43
+ }
44
+ };
45
+ const statusIcon = computed(() => STATUS_META[props.toolCall.status]?.icon ?? Loading);
46
+ const statusClass = computed(() => STATUS_META[props.toolCall.status]?.class ?? "");
47
+ /** 头部图标:工具自定义图标优先,缺省用状态图标(与工具卡片一致) */
48
+ const headerIcon = computed(() => tool.value?.icon ?? statusIcon.value);
49
+ /** 面板标题:优先工具定义的 panelTitle(业务对象 + 动作),缺省回落到 label ?? name */
50
+ const panelTitle = computed(() => {
51
+ const t = tool.value;
52
+ const pt = t?.panelTitle;
53
+ if (typeof pt === "function") return pt(props.toolCall);
54
+ return pt ?? t?.label ?? props.toolCall.name;
55
+ });
56
+ /** 未提供 render 时的兜底展示(面板工具通常都应提供 render) */
57
+ const fallbackResult = computed(() => {
58
+ const raw = props.toolCall.error ?? props.toolCall.result ?? "";
59
+ try {
60
+ return JSON.stringify(JSON.parse(raw), null, 2);
61
+ } catch {
62
+ return raw;
63
+ }
64
+ });
65
+ return (_ctx, _cache) => {
66
+ return openBlock(), createElementBlock("aside", { class: normalizeClass(unref(cls).e("panel")) }, [createElementVNode("div", { class: normalizeClass(unref(cls).e("panel-card")) }, [createElementVNode("div", { class: normalizeClass(unref(cls).e("panel-header")) }, [
67
+ createVNode(unref(UIcon), { class: normalizeClass([unref(cls).e("panel-icon"), statusClass.value]) }, {
68
+ default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(headerIcon.value)))]),
69
+ _: 1
70
+ }, 8, ["class"]),
71
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("panel-title")) }, toDisplayString(panelTitle.value), 3),
72
+ createVNode(unref(UIcon), {
73
+ class: normalizeClass(unref(cls).e("panel-close")),
74
+ title: "关闭面板",
75
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
76
+ }, {
77
+ default: withCtx(() => [createVNode(unref(Close))]),
78
+ _: 1
79
+ }, 8, ["class"])
80
+ ], 2), createVNode(unref(UScroll), { class: normalizeClass(unref(cls).e("panel-body")) }, {
81
+ default: withCtx(() => [createCommentVNode(" render 组件与工具卡片同一契约(ChatToolRenderProps),可随 toolCall 状态实时更新 "), tool.value?.render ? (openBlock(), createBlock(resolveDynamicComponent(tool.value.render), {
82
+ key: 0,
83
+ "tool-call": __props.toolCall
84
+ }, null, 8, ["tool-call"])) : (openBlock(), createElementBlock("pre", {
85
+ key: 1,
86
+ class: normalizeClass(unref(cls).e("panel-fallback"))
87
+ }, toDisplayString(fallbackResult.value), 3))]),
88
+ _: 1
89
+ }, 8, ["class"])], 2)], 2);
90
+ };
91
+ }
92
+ });
93
+ //#endregion
94
+ export { _sfc_main as default };
95
+
96
+ //# sourceMappingURL=side-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-panel.js","names":[],"sources":["../../../src/components/ai-chat/side-panel.vue"],"sourcesContent":["<template>\n <aside :class=\"cls.e('panel')\">\n <div :class=\"cls.e('panel-card')\">\n <div :class=\"cls.e('panel-header')\">\n <UIcon :class=\"[cls.e('panel-icon'), statusClass]\">\n <component :is=\"headerIcon\" />\n </UIcon>\n <span :class=\"cls.e('panel-title')\">{{ panelTitle }}</span>\n <UIcon :class=\"cls.e('panel-close')\" title=\"关闭面板\" @click=\"emit('close')\">\n <Close />\n </UIcon>\n </div>\n\n <UScroll :class=\"cls.e('panel-body')\">\n <!-- render 组件与工具卡片同一契约(ChatToolRenderProps),可随 toolCall 状态实时更新 -->\n <component :is=\"tool.render\" v-if=\"tool?.render\" :tool-call=\"toolCall\" />\n <pre v-else :class=\"cls.e('panel-fallback')\">{{ fallbackResult }}</pre>\n </UScroll>\n </div>\n </aside>\n</template>\n\n<script lang=\"ts\" setup>\nimport { UIcon, UScroll } from '@veltra/desktop'\nimport { CircleCheckFilled, CircleClose, Close, Loading, WarningFilled } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, inject, type Component } from 'vue'\n\nimport type { ChatToolCall } from '../../chat/types'\nimport { AiChatDIKey } from './di'\n\ndefineOptions({ name: 'UAiChatSidePanel' })\n\nconst props = defineProps<{ toolCall: ChatToolCall }>()\n\nconst emit = defineEmits<{ (e: 'close'): void }>()\n\nconst di = inject(AiChatDIKey)\nconst cls = di?.cls ?? bem('ai-chat')\n\n/** 当前调用对应的工具定义(解析 icon/label/render) */\nconst tool = computed(() => di?.tools.value[props.toolCall.name])\n\nconst STATUS_META: Record<string, { icon: Component; class: string }> = {\n pending: { icon: Loading, class: 'is-active' },\n running: { icon: Loading, class: 'is-active' },\n 'awaiting-confirm': { icon: WarningFilled, class: 'is-warning' },\n success: { icon: CircleCheckFilled, class: 'is-success' },\n error: { icon: CircleClose, class: 'is-danger' },\n rejected: { icon: Close, class: 'is-danger' }\n}\n\nconst statusIcon = computed(() => STATUS_META[props.toolCall.status]?.icon ?? Loading)\nconst statusClass = computed(() => STATUS_META[props.toolCall.status]?.class ?? '')\n\n/** 头部图标:工具自定义图标优先,缺省用状态图标(与工具卡片一致) */\nconst headerIcon = computed(() => tool.value?.icon ?? statusIcon.value)\n\n/** 面板标题:优先工具定义的 panelTitle(业务对象 + 动作),缺省回落到 label ?? name */\nconst panelTitle = computed(() => {\n const t = tool.value\n const pt = t?.panelTitle\n if (typeof pt === 'function') return pt(props.toolCall)\n return pt ?? t?.label ?? props.toolCall.name\n})\n\n/** 未提供 render 时的兜底展示(面板工具通常都应提供 render) */\nconst fallbackResult = computed(() => {\n const raw = props.toolCall.error ?? props.toolCall.result ?? ''\n try {\n return JSON.stringify(JSON.parse(raw), null, 2)\n } catch {\n return raw\n }\n})\n</script>\n"],"mappings":";;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,KAAK,OAAO,WAAW;EAC7B,MAAM,MAAM,IAAI,OAAO,IAAI,SAAS;;EAGpC,MAAM,OAAO,eAAe,IAAI,MAAM,MAAM,MAAM,SAAS,KAAK;EAEhE,MAAM,cAAkE;GACtE,SAAS;IAAE,MAAM;IAAS,OAAO;GAAY;GAC7C,SAAS;IAAE,MAAM;IAAS,OAAO;GAAY;GAC7C,oBAAoB;IAAE,MAAM;IAAe,OAAO;GAAa;GAC/D,SAAS;IAAE,MAAM;IAAmB,OAAO;GAAa;GACxD,OAAO;IAAE,MAAM;IAAa,OAAO;GAAY;GAC/C,UAAU;IAAE,MAAM;IAAO,OAAO;GAAY;EAC9C;EAEA,MAAM,aAAa,eAAe,YAAY,MAAM,SAAS,OAAO,EAAE,QAAQ,OAAO;EACrF,MAAM,cAAc,eAAe,YAAY,MAAM,SAAS,OAAO,EAAE,SAAS,EAAE;;EAGlF,MAAM,aAAa,eAAe,KAAK,OAAO,QAAQ,WAAW,KAAK;;EAGtE,MAAM,aAAa,eAAe;GAChC,MAAM,IAAI,KAAK;GACf,MAAM,KAAK,GAAG;GACd,IAAI,OAAO,OAAO,YAAY,OAAO,GAAG,MAAM,QAAQ;GACtD,OAAO,MAAM,GAAG,SAAS,MAAM,SAAS;EAC1C,CAAC;;EAGD,MAAM,iBAAiB,eAAe;GACpC,MAAM,MAAM,MAAM,SAAS,SAAS,MAAM,SAAS,UAAU;GAC7D,IAAI;IACF,OAAO,KAAK,UAAU,KAAK,MAAM,GAAG,GAAG,MAAM,CAAC;GAChD,QAAQ;IACN,OAAO;GACT;EACF,CAAC;;GAzEC,OAAA,UAAA,GAAA,mBAkBQ,SAAA,EAlBA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA,EAAA,GAClB,CAAA,mBAgBM,OAAA,EAhBA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA,EAAA,GAChB,CAAA,mBAQM,OAAA,EARA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA,CAAA,EAAA,GAAA;IAChB,YAEQ,MAAA,KAAA,GAAA,EAFA,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,GAAgB,YAAA,KAAW,CAAA,EAAA,GAAA;KAChB,SAAA,cAAA,EAAA,UAAA,GAA9B,YAA8B,wBAAd,WAAA,KAAU,CAAA,EAAA,CAAA;;;IAE5B,mBAA2D,QAAA,EAApD,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,aAAA,CAAA,EAAA,GAAoB,gBAAA,WAAA,KAAU,GAAA,CAAA;IACjD,YAEQ,MAAA,KAAA,GAAA;KAFA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,aAAA,CAAA;KAAiB,OAAM;KAAQ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,OAAA;;KACnD,SAAA,cAAA,CAAT,YAAS,MAAA,KAAA,CAAA,CAAA,CAAA;;;GAIb,GAAA,CAAA,GAAA,YAIU,MAAA,OAAA,GAAA,EAJA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA,EAAA,GAAA;IAC+C,SAAA,cAAA,CAAnE,mBAAA,8DAAA,GACmC,KAAA,OAAM,UAAA,UAAA,GAAzC,YAAyE,wBAAzD,KAAA,MAAK,MAAM,GAAA;;KAAuB,aAAW,QAAA;IAC7D,GAAA,MAAA,GAAA,CAAA,WAAA,CAAA,MAAA,UAAA,GAAA,mBAAuE,OAAA;;KAA1D,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,gBAAA,CAAA;IAAuB,GAAA,gBAAA,eAAA,KAAc,GAAA,CAAA,EAAA,CAAA"}
@@ -1,5 +1,11 @@
1
1
  import "@veltra/desktop/components/button/style";
2
+ import "@veltra/desktop/components/collapse/style";
3
+ import "@veltra/desktop/components/file-picker/style";
2
4
  import "@veltra/desktop/components/icon/style";
3
5
  import "@veltra/desktop/components/input/style";
6
+ import "@veltra/desktop/components/layout/style";
7
+ import "@veltra/desktop/components/message/style";
4
8
  import "@veltra/desktop/components/scroll/style";
9
+ import "@veltra/desktop/components/select/style";
10
+ import "@veltra/styles/animations/shine.scss";
5
11
  import "markstream-vue/index.css";
@@ -1,6 +1,12 @@
1
1
  import "./style2.css";
2
2
  import "@veltra/desktop/components/button/style";
3
+ import "@veltra/desktop/components/collapse/style";
4
+ import "@veltra/desktop/components/file-picker/style";
3
5
  import "@veltra/desktop/components/icon/style";
4
6
  import "@veltra/desktop/components/input/style";
7
+ import "@veltra/desktop/components/layout/style";
8
+ import "@veltra/desktop/components/message/style";
5
9
  import "@veltra/desktop/components/scroll/style";
10
+ import "@veltra/desktop/components/select/style";
11
+ import "@veltra/styles/animations/shine.scss";
6
12
  import "markstream-vue/index.css";