@frost1994/agentic-core 1.0.0 → 1.0.3

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.js CHANGED
@@ -570,6 +570,327 @@ class ChunkMatcher {
570
570
  return chunks.filter((c2) => !cited.has(c2.index));
571
571
  }
572
572
  }
573
+ function makeIndexes() {
574
+ return {
575
+ byPartId: /* @__PURE__ */ new Map(),
576
+ byToolCallId: /* @__PURE__ */ new Map(),
577
+ byCardId: /* @__PURE__ */ new Map()
578
+ };
579
+ }
580
+ function withMessages(state, messages) {
581
+ return { ...state, messages };
582
+ }
583
+ function replaceLast(messages, next) {
584
+ if (messages.length === 0) return messages;
585
+ return [...messages.slice(0, -1), next];
586
+ }
587
+ function lastMsg(state) {
588
+ return state.messages[state.messages.length - 1];
589
+ }
590
+ function replacePart(parts, index, next) {
591
+ const arr = [...parts];
592
+ arr[index] = next;
593
+ return arr;
594
+ }
595
+ function applyPatch(target, ops) {
596
+ let result = { ...target };
597
+ for (const op of ops) {
598
+ const match = /^\/([^/]+)$/.exec(op.path);
599
+ if (!match) continue;
600
+ const key = match[1];
601
+ if (op.op === "remove") {
602
+ const { [key]: _removed, ...rest } = result;
603
+ result = rest;
604
+ } else if (op.op === "add" || op.op === "replace") {
605
+ result = { ...result, [key]: op.value };
606
+ }
607
+ }
608
+ return result;
609
+ }
610
+ function initialState() {
611
+ return {
612
+ messages: [],
613
+ lastSeq: 0,
614
+ _idx: makeIndexes()
615
+ };
616
+ }
617
+ function reduce(state, event) {
618
+ if (event.type !== "run.start" && event.seq <= state.lastSeq) {
619
+ return state;
620
+ }
621
+ const nextSeq = event.seq;
622
+ const msg = lastMsg(state);
623
+ switch (event.type) {
624
+ case "run.start": {
625
+ const newMsg = {
626
+ messageId: event.messageId,
627
+ conversationId: event.conversationId,
628
+ status: "streaming",
629
+ parts: [],
630
+ startedAt: Date.now()
631
+ };
632
+ return {
633
+ messages: [...state.messages, newMsg],
634
+ lastSeq: nextSeq,
635
+ _idx: makeIndexes()
636
+ };
637
+ }
638
+ case "run.finish": {
639
+ if (!msg) return { ...state, lastSeq: nextSeq };
640
+ const finished = {
641
+ ...msg,
642
+ status: "complete",
643
+ usage: event.usage,
644
+ finishReason: event.reason,
645
+ latencyMs: event.latencyMs
646
+ };
647
+ return {
648
+ ...withMessages(state, replaceLast(state.messages, finished)),
649
+ lastSeq: nextSeq
650
+ };
651
+ }
652
+ case "run.error": {
653
+ if (!msg) return { ...state, lastSeq: nextSeq };
654
+ const errored = {
655
+ ...msg,
656
+ status: "error"
657
+ };
658
+ return {
659
+ ...withMessages(state, replaceLast(state.messages, errored)),
660
+ lastSeq: nextSeq
661
+ };
662
+ }
663
+ case "text.start": {
664
+ if (!msg) return { ...state, lastSeq: nextSeq };
665
+ const idx = msg.parts.length;
666
+ const newPart = { kind: "text", partId: event.partId, text: "" };
667
+ const nextIdx = { ...state._idx, byPartId: new Map(state._idx.byPartId) };
668
+ nextIdx.byPartId.set(event.partId, idx);
669
+ const nextMsg = { ...msg, parts: [...msg.parts, newPart] };
670
+ return {
671
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
672
+ lastSeq: nextSeq,
673
+ _idx: nextIdx
674
+ };
675
+ }
676
+ case "text.delta": {
677
+ if (!msg) return { ...state, lastSeq: nextSeq };
678
+ const idx = state._idx.byPartId.get(event.partId);
679
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
680
+ const part = msg.parts[idx];
681
+ const updated = { ...part, text: part.text + event.delta };
682
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
683
+ return {
684
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
685
+ lastSeq: nextSeq
686
+ };
687
+ }
688
+ case "text.end": {
689
+ return { ...state, lastSeq: nextSeq };
690
+ }
691
+ case "reasoning.start": {
692
+ if (!msg) return { ...state, lastSeq: nextSeq };
693
+ const idx = msg.parts.length;
694
+ const newPart = { kind: "reasoning", partId: event.partId, text: "" };
695
+ const nextIdx = { ...state._idx, byPartId: new Map(state._idx.byPartId) };
696
+ nextIdx.byPartId.set(event.partId, idx);
697
+ const nextMsg = { ...msg, parts: [...msg.parts, newPart] };
698
+ return {
699
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
700
+ lastSeq: nextSeq,
701
+ _idx: nextIdx
702
+ };
703
+ }
704
+ case "reasoning.delta": {
705
+ if (!msg) return { ...state, lastSeq: nextSeq };
706
+ const idx = state._idx.byPartId.get(event.partId);
707
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
708
+ const part = msg.parts[idx];
709
+ const updated = { ...part, text: part.text + event.delta };
710
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
711
+ return {
712
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
713
+ lastSeq: nextSeq
714
+ };
715
+ }
716
+ case "reasoning.end": {
717
+ return { ...state, lastSeq: nextSeq };
718
+ }
719
+ case "tool.start": {
720
+ if (!msg) return { ...state, lastSeq: nextSeq };
721
+ const idx = msg.parts.length;
722
+ const newPart = {
723
+ kind: "tool",
724
+ toolCallId: event.toolCallId,
725
+ toolName: event.toolName,
726
+ status: "pending"
727
+ };
728
+ const nextIdx = { ...state._idx, byToolCallId: new Map(state._idx.byToolCallId) };
729
+ nextIdx.byToolCallId.set(event.toolCallId, idx);
730
+ const nextMsg = { ...msg, parts: [...msg.parts, newPart] };
731
+ return {
732
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
733
+ lastSeq: nextSeq,
734
+ _idx: nextIdx
735
+ };
736
+ }
737
+ case "tool.input.delta": {
738
+ if (!msg) return { ...state, lastSeq: nextSeq };
739
+ const idx = state._idx.byToolCallId.get(event.toolCallId);
740
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
741
+ const part = msg.parts[idx];
742
+ const updated = {
743
+ ...part,
744
+ status: "input-streaming",
745
+ inputRaw: (part.inputRaw ?? "") + event.delta
746
+ };
747
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
748
+ return {
749
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
750
+ lastSeq: nextSeq
751
+ };
752
+ }
753
+ case "tool.input": {
754
+ if (!msg) return { ...state, lastSeq: nextSeq };
755
+ const idx = state._idx.byToolCallId.get(event.toolCallId);
756
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
757
+ const part = msg.parts[idx];
758
+ const updated = {
759
+ ...part,
760
+ status: "input-ready",
761
+ input: event.input
762
+ };
763
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
764
+ return {
765
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
766
+ lastSeq: nextSeq
767
+ };
768
+ }
769
+ case "tool.executing": {
770
+ if (!msg) return { ...state, lastSeq: nextSeq };
771
+ const idx = state._idx.byToolCallId.get(event.toolCallId);
772
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
773
+ const part = msg.parts[idx];
774
+ const updated = { ...part, status: "executing" };
775
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
776
+ return {
777
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
778
+ lastSeq: nextSeq
779
+ };
780
+ }
781
+ case "tool.output": {
782
+ if (!msg) return { ...state, lastSeq: nextSeq };
783
+ const idx = state._idx.byToolCallId.get(event.toolCallId);
784
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
785
+ const part = msg.parts[idx];
786
+ const updated = {
787
+ ...part,
788
+ status: event.status === "output-available" ? "output-available" : "output-error",
789
+ output: event.output,
790
+ outputStatus: event.status
791
+ };
792
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
793
+ return {
794
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
795
+ lastSeq: nextSeq
796
+ };
797
+ }
798
+ case "tool.error": {
799
+ if (!msg) return { ...state, lastSeq: nextSeq };
800
+ const idx = state._idx.byToolCallId.get(event.toolCallId);
801
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
802
+ const part = msg.parts[idx];
803
+ const updated = { ...part, status: "output-error", error: event.error };
804
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
805
+ return {
806
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
807
+ lastSeq: nextSeq
808
+ };
809
+ }
810
+ case "card": {
811
+ if (!msg) return { ...state, lastSeq: nextSeq };
812
+ const existing = state._idx.byCardId.get(event.id);
813
+ const newPart = {
814
+ kind: "card",
815
+ id: event.id,
816
+ cardKind: event.kind,
817
+ data: event.data,
818
+ transient: event.transient,
819
+ status: event.status
820
+ };
821
+ if (existing !== void 0) {
822
+ const nextMsg2 = {
823
+ ...msg,
824
+ parts: replacePart(msg.parts, existing, newPart)
825
+ };
826
+ return {
827
+ ...withMessages(state, replaceLast(state.messages, nextMsg2)),
828
+ lastSeq: nextSeq
829
+ };
830
+ }
831
+ const idx = msg.parts.length;
832
+ const nextIdx = { ...state._idx, byCardId: new Map(state._idx.byCardId) };
833
+ nextIdx.byCardId.set(event.id, idx);
834
+ const nextMsg = { ...msg, parts: [...msg.parts, newPart] };
835
+ return {
836
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
837
+ lastSeq: nextSeq,
838
+ _idx: nextIdx
839
+ };
840
+ }
841
+ case "card.patch": {
842
+ if (!msg) return { ...state, lastSeq: nextSeq };
843
+ const idx = state._idx.byCardId.get(event.id);
844
+ if (idx === void 0) return { ...state, lastSeq: nextSeq };
845
+ const part = msg.parts[idx];
846
+ const patchedData = applyPatch(
847
+ part.data,
848
+ event.patch
849
+ );
850
+ const updated = { ...part, data: patchedData };
851
+ const nextMsg = { ...msg, parts: replacePart(msg.parts, idx, updated) };
852
+ return {
853
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
854
+ lastSeq: nextSeq
855
+ };
856
+ }
857
+ case "action.proposed": {
858
+ if (!msg) return { ...state, lastSeq: nextSeq };
859
+ const newPart = {
860
+ kind: "action",
861
+ actionId: event.actionId,
862
+ title: event.title,
863
+ summary: event.summary,
864
+ riskLevel: event.riskLevel,
865
+ params: event.params
866
+ };
867
+ const nextMsg = { ...msg, parts: [...msg.parts, newPart] };
868
+ return {
869
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
870
+ lastSeq: nextSeq
871
+ };
872
+ }
873
+ case "clarify": {
874
+ if (!msg) return { ...state, lastSeq: nextSeq };
875
+ const newPart = {
876
+ kind: "clarify",
877
+ question: event.question,
878
+ options: event.options
879
+ };
880
+ const nextMsg = { ...msg, parts: [...msg.parts, newPart] };
881
+ return {
882
+ ...withMessages(state, replaceLast(state.messages, nextMsg)),
883
+ lastSeq: nextSeq
884
+ };
885
+ }
886
+ default: {
887
+ return { ...state, lastSeq: nextSeq };
888
+ }
889
+ }
890
+ }
891
+ function reduceAll(events) {
892
+ return events.reduce(reduce, initialState());
893
+ }
573
894
  export {
574
895
  AiHttpClient,
575
896
  AiHttpError,
@@ -591,6 +912,7 @@ export {
591
912
  h as formatDate,
592
913
  i as formatDuration,
593
914
  generateId,
915
+ initialState,
594
916
  j as isAborted,
595
917
  k as isArray,
596
918
  l as isFunction,
@@ -598,6 +920,8 @@ export {
598
920
  n as isObject,
599
921
  o as isRetriable,
600
922
  p as isString,
923
+ reduce,
924
+ reduceAll,
601
925
  reducer,
602
926
  serialize,
603
927
  serializeToString,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/http.ts","../src/state/index.ts","../src/orchestrator/index.ts","../src/knowledge/index.ts"],"sourcesContent":["/**\r\n * AI Assistant REST HTTP Client\r\n *\r\n * Zero-dependency HTTP client for communicating with the Frost AI backend.\r\n * Automatically unwraps `Result<T>` responses (`{ code, message, data, traceId }`).\r\n * Designed for the core package with no framework dependency.\r\n */\r\n\r\nimport type {\r\n AssistantMessage,\r\n Conversation,\r\n ModelOption,\r\n} from './protocol/types'\r\n\r\ninterface ApiResult<T> {\r\n code: number\r\n message: string\r\n data: T\r\n traceId?: string\r\n}\r\n\r\nexport interface PluginConfig {\r\n systemCode: string\r\n defaultMode: string\r\n themeStrategy: string\r\n themePreset: string\r\n primaryColor: string\r\n defaultModelCode: string\r\n enableFullscreen: boolean\r\n enableDrawer: boolean\r\n enableKnowledge: boolean\r\n enableText2Sql: boolean\r\n rateLimitPerHour: number\r\n}\r\n\r\nexport interface DataSourceItem {\r\n code: string\r\n name: string\r\n type: string\r\n description?: string\r\n}\r\n\r\nexport interface TableInfo {\r\n tableName: string\r\n tableComment?: string\r\n columns?: Array<{\r\n columnName: string\r\n columnType: string\r\n columnComment?: string\r\n sensitive?: boolean\r\n }>\r\n}\r\n\r\nexport class AiHttpError extends Error {\r\n readonly code: number\r\n readonly traceId?: string\r\n\r\n constructor(code: number, message: string, traceId?: string) {\r\n super(message)\r\n this.name = 'AiHttpError'\r\n this.code = code\r\n this.traceId = traceId\r\n }\r\n}\r\n\r\nexport class AiHttpClient {\r\n private readonly baseUrl: string\r\n private readonly headersProvider: () => Record<string, string>\r\n\r\n constructor(baseUrl: string, headersProvider: () => Record<string, string>) {\r\n this.baseUrl = baseUrl.replace(/\\/+$/, '')\r\n this.headersProvider = headersProvider\r\n }\r\n\r\n async getPluginConfig(systemCode: string): Promise<PluginConfig | null> {\r\n const raw = await this.request<Record<string, unknown>>(\r\n 'GET',\r\n `/plugin/config?systemCode=${encodeURIComponent(systemCode)}`,\r\n ).catch(() => null)\r\n\r\n if (!raw) {\r\n return null\r\n }\r\n\r\n return {\r\n systemCode: (raw.systemCode as string) ?? systemCode,\r\n defaultMode: (raw.defaultMode as string) ?? 'floating',\r\n themeStrategy: (raw.themeStrategy as string) ?? 'system',\r\n themePreset: (raw.themePreset as string) ?? 'light',\r\n primaryColor: (raw.primaryColor as string) ?? '#409EFF',\r\n defaultModelCode: (raw.defaultModelCode as string) ?? 'default',\r\n enableFullscreen: Boolean(raw.enableFullscreen ?? true),\r\n enableDrawer: Boolean(raw.enableDrawer ?? true),\r\n enableKnowledge: Boolean(raw.enableKnowledge ?? false),\r\n enableText2Sql: Boolean(raw.enableText2Sql ?? true),\r\n rateLimitPerHour: Number(raw.rateLimitPerHour ?? 100),\r\n }\r\n }\r\n\r\n async listModels(): Promise<ModelOption[]> {\r\n const raw = await this.request<Array<Record<string, unknown>>>('GET', '/models')\r\n\r\n return raw.map((item) => ({\r\n code: (item.code as string) ?? (item.modelCode as string) ?? '',\r\n name: (item.name as string) ?? (item.modelName as string) ?? '',\r\n supportStream: Boolean(item.supportStream ?? true),\r\n supportToolCall: Boolean(item.supportToolCall ?? false),\r\n bestFor: ((item.bestFor as ModelOption['bestFor']) ?? []).filter(Boolean),\r\n maxTokens: typeof item.maxTokens === 'number' ? item.maxTokens : undefined,\r\n })).filter((item) => item.code && item.name)\r\n }\r\n\r\n async createConversation(\r\n systemCode: string,\r\n title?: string,\r\n modelCode?: string,\r\n ): Promise<Conversation> {\r\n return this.request<Conversation>('POST', '/conversations', {\r\n systemCode,\r\n title: title ?? 'New conversation',\r\n modelCode: modelCode ?? 'default',\r\n })\r\n }\r\n\r\n async listConversations(\r\n systemCode: string,\r\n page = 1,\r\n size = 20,\r\n ): Promise<Conversation[]> {\r\n return this.request<Conversation[]>(\r\n 'GET',\r\n `/conversations?systemCode=${encodeURIComponent(systemCode)}&page=${page}&size=${size}`,\r\n )\r\n }\r\n\r\n async getMessages(conversationId: string): Promise<AssistantMessage[]> {\r\n return this.request<AssistantMessage[]>(\r\n 'GET',\r\n `/conversations/${encodeURIComponent(conversationId)}/messages`,\r\n )\r\n }\r\n\r\n async deleteConversation(conversationId: string): Promise<void> {\r\n await this.request<void>(\r\n 'DELETE',\r\n `/conversations/${encodeURIComponent(conversationId)}`,\r\n )\r\n }\r\n\r\n async getSuggestions(systemCode: string, sceneCode?: string): Promise<string[]> {\r\n let path = `/suggestions?systemCode=${encodeURIComponent(systemCode)}`\r\n if (sceneCode) {\r\n path += `&sceneCode=${encodeURIComponent(sceneCode)}`\r\n }\r\n return this.request<string[]>('GET', path)\r\n }\r\n\r\n async confirmAction(actionId: string, confirm: boolean): Promise<void> {\r\n await this.request<void>('POST', '/actions/confirm', {\r\n actionId,\r\n confirm,\r\n })\r\n }\r\n\r\n async listDataSources(): Promise<DataSourceItem[]> {\r\n const raw = await this.request<Array<Record<string, unknown>>>('GET', '/data-sources')\r\n\r\n return raw.map((item) => ({\r\n code: (item.code as string) ?? (item.sourceCode as string) ?? '',\r\n name: (item.name as string) ?? (item.sourceName as string) ?? '',\r\n type: (item.type as string) ?? (item.dbType as string) ?? '',\r\n description: item.description as string | undefined,\r\n })).filter((item) => item.code && item.name)\r\n }\r\n\r\n async listTables(dataSourceCode: string): Promise<TableInfo[]> {\r\n const raw = await this.request<Array<Record<string, unknown>>>(\r\n 'GET',\r\n `/data-sources/${encodeURIComponent(dataSourceCode)}/tables`,\r\n )\r\n\r\n return raw.map((item) => ({\r\n tableName: (item.tableName as string) ?? '',\r\n tableComment:\r\n (item.tableComment as string)\r\n ?? (item.tableAlias as string)\r\n ?? (item.description as string)\r\n ?? undefined,\r\n columns: Array.isArray(item.columns) ? item.columns as TableInfo['columns'] : undefined,\r\n })).filter((item) => item.tableName)\r\n }\r\n\r\n async submitFeedback(\r\n messageId: string,\r\n rating: number,\r\n comment?: string,\r\n ): Promise<void> {\r\n await this.request<void>('POST', '/feedback', {\r\n messageId,\r\n rating,\r\n comment,\r\n })\r\n }\r\n\r\n async health(): Promise<{ status: string; service: string }> {\r\n const healthUrl = this.baseUrl.endsWith('/api/ai')\r\n ? `${this.baseUrl.slice(0, -'/api/ai'.length)}/actuator/health`\r\n : `${this.baseUrl}/health`\r\n\r\n const res = await fetch(healthUrl, {\r\n method: 'GET',\r\n headers: this.headersProvider(),\r\n })\r\n\r\n if (!res.ok) {\r\n throw new AiHttpError(res.status, `HTTP ${res.status}: ${res.statusText}`)\r\n }\r\n\r\n const json = await res.json() as ApiResult<{ status: string; service: string }> | { status: string }\r\n if ('code' in json) {\r\n if (json.code !== 200) {\r\n throw new AiHttpError(json.code, json.message ?? 'Unknown API error', json.traceId)\r\n }\r\n return json.data\r\n }\r\n\r\n return {\r\n status: json.status,\r\n service: 'ai-gateway',\r\n }\r\n }\r\n\r\n private async request<T>(\r\n method: string,\r\n path: string,\r\n body?: unknown,\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`\r\n const headers = {\r\n 'Content-Type': 'application/json',\r\n ...this.headersProvider(),\r\n }\r\n\r\n const init: RequestInit = {\r\n method,\r\n headers,\r\n }\r\n\r\n if (body !== undefined && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {\r\n init.body = JSON.stringify(body)\r\n }\r\n\r\n const res = await fetch(url, init)\r\n if (!res.ok) {\r\n throw new AiHttpError(res.status, `HTTP ${res.status}: ${res.statusText}`)\r\n }\r\n\r\n if (res.status === 204 || method === 'DELETE') {\r\n return undefined as T\r\n }\r\n\r\n const json = await res.json() as ApiResult<T>\r\n if (json.code !== undefined && json.code !== 200) {\r\n throw new AiHttpError(\r\n json.code,\r\n json.message ?? 'Unknown API error',\r\n json.traceId,\r\n )\r\n }\r\n\r\n return json.data as T\r\n }\r\n}\r\n","/**\r\n * Pure TypeScript state management for AI Assistant Core\r\n *\r\n * No Vue / React / Pinia dependency.\r\n * Can be wrapped by any framework's reactive system.\r\n */\r\n\r\nimport type {\r\n AiOpenMode,\r\n AiThemeMode,\r\n AssistantMessage,\r\n Conversation,\r\n MessageStatus,\r\n ToolStep,\r\n} from '../protocol'\r\n\r\n// ---------------------------------------------------------------------------\r\n// State shape\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface AssistantState {\r\n /** UI visibility */\r\n visible: boolean\r\n /** Current display mode */\r\n mode: AiOpenMode\r\n /** Previous mode before switch (for back-navigation) */\r\n previousMode: AiOpenMode | null\r\n /** Floating window position (px) */\r\n position: { x: number; y: number }\r\n /** Floating window size (px) */\r\n size: { width: number; height: number }\r\n /** Business system code */\r\n systemCode: string\r\n /** Selected model code */\r\n modelCode: string\r\n /** Current conversation id */\r\n currentConversationId: string | null\r\n /** All loaded conversations */\r\n conversations: Conversation[]\r\n /** Messages keyed by conversation id */\r\n messagesByConversation: Record<string, AssistantMessage[]>\r\n /** Tool steps keyed by message id */\r\n toolStepsByMessage: Record<string, ToolStep[]>\r\n /** Stream connection status */\r\n streamStatus: 'idle' | 'connecting' | 'streaming' | 'reconnecting' | 'closed' | 'error'\r\n /** Last received sequence number (for ack / resume) */\r\n lastSeq: number\r\n /** Last heartbeat timestamp */\r\n lastHeartbeatAt: number\r\n /** Reconnect attempt counter */\r\n reconnectAttempt: number\r\n /** Theme mode */\r\n themeMode: AiThemeMode\r\n /** Primary color */\r\n primaryColor: string\r\n /** Whether an error toast is currently shown */\r\n hasError: boolean\r\n /** Last error message (transient) */\r\n lastError: string | null\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Action types (discriminated union for reducer)\r\n// ---------------------------------------------------------------------------\r\n\r\nexport type StateAction =\r\n | { type: 'OPEN'; mode?: AiOpenMode }\r\n | { type: 'CLOSE' }\r\n | { type: 'TOGGLE' }\r\n | { type: 'SWITCH_MODE'; mode: AiOpenMode }\r\n | { type: 'SET_POSITION'; x: number; y: number }\r\n | { type: 'SET_SIZE'; width: number; height: number }\r\n | { type: 'SET_SYSTEM_CODE'; systemCode: string }\r\n | { type: 'SET_MODEL_CODE'; modelCode: string }\r\n | { type: 'SET_CONVERSATION'; id: string | null }\r\n | { type: 'ADD_CONVERSATION'; conversation: Conversation }\r\n | { type: 'SET_CONVERSATIONS'; conversations: Conversation[] }\r\n | { type: 'APPEND_MESSAGE'; conversationId: string; message: AssistantMessage }\r\n | { type: 'APPEND_DELTA'; conversationId: string; messageId: string; delta: string }\r\n | { type: 'UPDATE_MESSAGE_STATUS'; conversationId: string; messageId: string; status: MessageStatus }\r\n | { type: 'SET_MESSAGES'; conversationId: string; messages: AssistantMessage[] }\r\n | { type: 'APPEND_TOOL_STEP'; messageId: string; step: ToolStep }\r\n | { type: 'UPDATE_TOOL_STEP'; messageId: string; stepId: string; patch: Partial<ToolStep> }\r\n | { type: 'SET_STREAM_STATUS'; status: AssistantState['streamStatus'] }\r\n | { type: 'SET_LAST_SEQ'; seq: number }\r\n | { type: 'SET_HEARTBEAT'; ts: number }\r\n | { type: 'INCREMENT_RECONNECT' }\r\n | { type: 'RESET_RECONNECT' }\r\n | { type: 'SET_THEME'; mode: AiThemeMode }\r\n | { type: 'SET_PRIMARY_COLOR'; color: string }\r\n | { type: 'SET_ERROR'; error: string | null }\r\n | { type: 'HYDRATE'; state: Partial<AssistantState> }\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function createInitialState(overrides?: Partial<AssistantState>): AssistantState {\r\n return {\r\n visible: false,\r\n mode: 'floating',\r\n previousMode: null,\r\n position: { x: 0, y: 0 },\r\n size: { width: 420, height: 600 },\r\n systemCode: '',\r\n modelCode: '',\r\n currentConversationId: null,\r\n conversations: [],\r\n messagesByConversation: {},\r\n toolStepsByMessage: {},\r\n streamStatus: 'idle',\r\n lastSeq: 0,\r\n lastHeartbeatAt: 0,\r\n reconnectAttempt: 0,\r\n themeMode: 'system',\r\n primaryColor: '#1677ff',\r\n hasError: false,\r\n lastError: null,\r\n ...overrides,\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Reducer (pure function)\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function reducer(state: AssistantState, action: StateAction): AssistantState {\r\n switch (action.type) {\r\n case 'OPEN':\r\n return {\r\n ...state,\r\n visible: true,\r\n mode: action.mode ?? state.mode,\r\n }\r\n\r\n case 'CLOSE':\r\n return { ...state, visible: false }\r\n\r\n case 'TOGGLE':\r\n return { ...state, visible: !state.visible }\r\n\r\n case 'SWITCH_MODE': {\r\n return {\r\n ...state,\r\n previousMode: state.mode,\r\n mode: action.mode,\r\n }\r\n }\r\n\r\n case 'SET_POSITION':\r\n return {\r\n ...state,\r\n position: { x: action.x, y: action.y },\r\n }\r\n\r\n case 'SET_SIZE':\r\n return {\r\n ...state,\r\n size: { width: action.width, height: action.height },\r\n }\r\n\r\n case 'SET_SYSTEM_CODE':\r\n return { ...state, systemCode: action.systemCode }\r\n\r\n case 'SET_MODEL_CODE':\r\n return { ...state, modelCode: action.modelCode }\r\n\r\n case 'SET_CONVERSATION':\r\n return { ...state, currentConversationId: action.id }\r\n\r\n case 'ADD_CONVERSATION': {\r\n const next = [action.conversation, ...state.conversations]\r\n return { ...state, conversations: next }\r\n }\r\n\r\n case 'SET_CONVERSATIONS':\r\n return { ...state, conversations: action.conversations }\r\n\r\n case 'APPEND_MESSAGE': {\r\n const list = state.messagesByConversation[action.conversationId] ?? []\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: [...list, action.message],\r\n },\r\n }\r\n }\r\n\r\n case 'APPEND_DELTA': {\r\n const list = state.messagesByConversation[action.conversationId]\r\n if (!list) return state\r\n const idx = list.findIndex(m => m.id === action.messageId)\r\n if (idx === -1) return state\r\n const next = list.slice()\r\n next[idx] = { ...next[idx], content: next[idx].content + action.delta }\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: next,\r\n },\r\n }\r\n }\r\n\r\n case 'UPDATE_MESSAGE_STATUS': {\r\n const list = state.messagesByConversation[action.conversationId]\r\n if (!list) return state\r\n const idx = list.findIndex(m => m.id === action.messageId)\r\n if (idx === -1) return state\r\n const next = list.slice()\r\n const msg = next[idx]\r\n next[idx] = {\r\n ...msg,\r\n status: action.status,\r\n finishedAt:\r\n action.status === 'success' || action.status === 'failed'\r\n ? new Date().toISOString()\r\n : msg.finishedAt,\r\n }\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: next,\r\n },\r\n }\r\n }\r\n\r\n case 'SET_MESSAGES':\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: action.messages,\r\n },\r\n }\r\n\r\n case 'APPEND_TOOL_STEP': {\r\n const steps = state.toolStepsByMessage[action.messageId] ?? []\r\n return {\r\n ...state,\r\n toolStepsByMessage: {\r\n ...state.toolStepsByMessage,\r\n [action.messageId]: [...steps, action.step],\r\n },\r\n }\r\n }\r\n\r\n case 'UPDATE_TOOL_STEP': {\r\n const steps = state.toolStepsByMessage[action.messageId]\r\n if (!steps) return state\r\n const idx = steps.findIndex(s => s.stepId === action.stepId)\r\n if (idx === -1) return state\r\n const next = steps.slice()\r\n next[idx] = { ...next[idx], ...action.patch }\r\n return {\r\n ...state,\r\n toolStepsByMessage: {\r\n ...state.toolStepsByMessage,\r\n [action.messageId]: next,\r\n },\r\n }\r\n }\r\n\r\n case 'SET_STREAM_STATUS':\r\n return { ...state, streamStatus: action.status }\r\n\r\n case 'SET_LAST_SEQ':\r\n return { ...state, lastSeq: action.seq }\r\n\r\n case 'SET_HEARTBEAT':\r\n return { ...state, lastHeartbeatAt: action.ts }\r\n\r\n case 'INCREMENT_RECONNECT':\r\n return { ...state, reconnectAttempt: state.reconnectAttempt + 1 }\r\n\r\n case 'RESET_RECONNECT':\r\n return { ...state, reconnectAttempt: 0 }\r\n\r\n case 'SET_THEME':\r\n return { ...state, themeMode: action.mode }\r\n\r\n case 'SET_PRIMARY_COLOR':\r\n return { ...state, primaryColor: action.color }\r\n\r\n case 'SET_ERROR':\r\n return {\r\n ...state,\r\n hasError: action.error !== null,\r\n lastError: action.error,\r\n }\r\n\r\n case 'HYDRATE':\r\n return { ...state, ...action.state }\r\n\r\n default:\r\n return state\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Serialization / Deserialization\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface SerializedState {\r\n version: number\r\n state: Omit<AssistantState, 'streamStatus' | 'lastSeq' | 'lastHeartbeatAt' | 'reconnectAttempt' | 'hasError' | 'lastError'>\r\n}\r\n\r\nconst SERIAL_VERSION = 1\r\n\r\n/** Serialize state to JSON-safe object (excludes transient stream fields). */\r\nexport function serialize(state: AssistantState): SerializedState {\r\n const {\r\n streamStatus,\r\n lastSeq,\r\n lastHeartbeatAt,\r\n reconnectAttempt,\r\n hasError,\r\n lastError,\r\n ...persistable\r\n } = state\r\n void streamStatus\r\n void lastSeq\r\n void lastHeartbeatAt\r\n void reconnectAttempt\r\n void hasError\r\n void lastError\r\n return { version: SERIAL_VERSION, state: persistable as SerializedState['state'] }\r\n}\r\n\r\n/** Deserialize and merge with fresh initial state defaults. */\r\nexport function deserialize(data: unknown): AssistantState | null {\r\n if (!data || typeof data !== 'object') return null\r\n const parsed = data as SerializedState\r\n if (parsed.version !== SERIAL_VERSION) return null\r\n return createInitialState(parsed.state)\r\n}\r\n\r\n/** Convenience: serialize to JSON string. */\r\nexport function serializeToString(state: AssistantState): string {\r\n return JSON.stringify(serialize(state))\r\n}\r\n\r\n/** Convenience: deserialize from JSON string. */\r\nexport function deserializeFromString(json: string): AssistantState | null {\r\n try {\r\n return deserialize(JSON.parse(json))\r\n } catch {\r\n return null\r\n }\r\n}\r\n","/**\r\n * Tool-call orchestrator for AI Assistant Core\r\n *\r\n * ToolRegistry — register / lookup tools\r\n * ToolOrchestrator — execute steps in parallel or serial order\r\n */\r\n\r\nimport type { ToolDefinition, ToolExecutor, ToolStep } from '../protocol'\r\nimport { generateId } from '../utils'\r\n\r\n// ---------------------------------------------------------------------------\r\n// ToolRegistry\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface RegisteredTool {\r\n definition: ToolDefinition\r\n executor: ToolExecutor\r\n}\r\n\r\nexport class ToolRegistry {\r\n private readonly tools = new Map<string, RegisteredTool>()\r\n\r\n /** Register a tool with its definition and executor. */\r\n register(definition: ToolDefinition, executor: ToolExecutor): void {\r\n this.tools.set(definition.name, { definition, executor })\r\n }\r\n\r\n /** Unregister a tool by name. */\r\n unregister(name: string): boolean {\r\n return this.tools.delete(name)\r\n }\r\n\r\n /** Look up a registered tool. */\r\n get(name: string): RegisteredTool | undefined {\r\n return this.tools.get(name)\r\n }\r\n\r\n /** Check whether a tool is registered. */\r\n has(name: string): boolean {\r\n return this.tools.has(name)\r\n }\r\n\r\n /** List all registered tool names. */\r\n list(): string[] {\r\n return Array.from(this.tools.keys())\r\n }\r\n\r\n /** Get all definitions (for sending to LLM). */\r\n getDefinitions(): ToolDefinition[] {\r\n return Array.from(this.tools.values()).map(t => t.definition)\r\n }\r\n\r\n /** Clear all registrations. */\r\n clear(): void {\r\n this.tools.clear()\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// ToolOrchestrator\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface OrchestratorOptions {\r\n registry: ToolRegistry\r\n onStepStart?: (step: ToolStep) => void\r\n onStepProgress?: (stepId: string, percent: number, message?: string) => void\r\n onStepComplete?: (step: ToolStep) => void\r\n onStepError?: (step: ToolStep, error: Error) => void\r\n}\r\n\r\nexport type ExecutionMode = 'parallel' | 'serial'\r\n\r\nexport interface ExecutionPlan {\r\n mode: ExecutionMode\r\n steps: Array<{\r\n toolName: string\r\n args: Record<string, unknown>\r\n title?: string\r\n }>\r\n}\r\n\r\nexport class ToolOrchestrator {\r\n private readonly registry: ToolRegistry\r\n private readonly onStepStart?: (step: ToolStep) => void\r\n private readonly onStepComplete?: (step: ToolStep) => void\r\n private readonly onStepError?: (step: ToolStep, error: Error) => void\r\n\r\n constructor(options: OrchestratorOptions) {\r\n this.registry = options.registry\r\n this.onStepStart = options.onStepStart\r\n this.onStepComplete = options.onStepComplete\r\n this.onStepError = options.onStepError\r\n }\r\n\r\n /**\r\n * Execute a plan of tool steps.\r\n *\r\n * - `serial`: steps run one after another; if one fails, abort the rest.\r\n * - `parallel`: steps run concurrently; all results collected regardless of individual failures.\r\n */\r\n async execute(plan: ExecutionPlan): Promise<ToolStep[]> {\r\n if (plan.mode === 'serial') {\r\n return this.executeSerial(plan.steps)\r\n }\r\n return this.executeParallel(plan.steps)\r\n }\r\n\r\n /** Execute a single tool step. */\r\n async executeSingle(\r\n toolName: string,\r\n args: Record<string, unknown>,\r\n title?: string\r\n ): Promise<ToolStep> {\r\n const registered = this.registry.get(toolName)\r\n if (!registered) {\r\n const step: ToolStep = {\r\n stepId: generateId('step_'),\r\n toolName,\r\n title: title ?? toolName,\r\n status: 'error',\r\n args,\r\n message: `Tool \"${toolName}\" is not registered`,\r\n }\r\n this.onStepError?.(step, new Error(step.message))\r\n return step\r\n }\r\n\r\n const step: ToolStep = {\r\n stepId: generateId('step_'),\r\n toolName,\r\n title: title ?? registered.definition.description ?? toolName,\r\n status: 'running',\r\n args,\r\n }\r\n\r\n this.onStepStart?.(step)\r\n\r\n const startTime = Date.now()\r\n try {\r\n const result = await registered.executor(args)\r\n step.status = 'success'\r\n step.result = result\r\n step.durationMs = Date.now() - startTime\r\n this.onStepComplete?.(step)\r\n return step\r\n } catch (err) {\r\n step.status = 'error'\r\n step.result = err instanceof Error ? err.message : String(err)\r\n step.durationMs = Date.now() - startTime\r\n this.onStepError?.(step, err instanceof Error ? err : new Error(String(err)))\r\n return step\r\n }\r\n }\r\n\r\n private async executeSerial(\r\n steps: ExecutionPlan['steps']\r\n ): Promise<ToolStep[]> {\r\n const results: ToolStep[] = []\r\n for (const s of steps) {\r\n const result = await this.executeSingle(s.toolName, s.args, s.title)\r\n results.push(result)\r\n if (result.status === 'error') {\r\n // Abort remaining serial steps\r\n break\r\n }\r\n }\r\n return results\r\n }\r\n\r\n private async executeParallel(\r\n steps: ExecutionPlan['steps']\r\n ): Promise<ToolStep[]> {\r\n return Promise.all(\r\n steps.map(s => this.executeSingle(s.toolName, s.args, s.title))\r\n )\r\n }\r\n}\r\n","/**\r\n * Knowledge-base citation parser for AI Assistant Core\r\n *\r\n * Parses [1] [2] citation markers in assistant text and\r\n * matches them against content chunks returned by the backend.\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// CitationParser\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface Citation {\r\n /** Raw marker text, e.g. \"[1]\" */\r\n marker: string\r\n /** Numeric index, e.g. 1 */\r\n index: number\r\n /** Start position in the source text */\r\n start: number\r\n /** End position in the source text */\r\n end: number\r\n}\r\n\r\nexport class CitationParser {\r\n /** Regex for citation markers: [1], [12], etc. */\r\n private static readonly MARKER_RE = /\\[(\\d+)\\]/g\r\n\r\n /**\r\n * Extract all citation markers from a text block.\r\n *\r\n * @param text — source text containing [1], [2], … markers\r\n * @returns ordered list of citations with positions\r\n */\r\n parse(text: string): Citation[] {\r\n const citations: Citation[] = []\r\n let match: RegExpExecArray | null\r\n CitationParser.MARKER_RE.lastIndex = 0\r\n while ((match = CitationParser.MARKER_RE.exec(text)) !== null) {\r\n citations.push({\r\n marker: match[0],\r\n index: parseInt(match[1], 10),\r\n start: match.index,\r\n end: match.index + match[0].length,\r\n })\r\n }\r\n return citations\r\n }\r\n\r\n /**\r\n * Strip citation markers from text, returning clean text and a mapping.\r\n *\r\n * @returns `{ text: string, citations: Citation[] }`\r\n */\r\n strip(text: string): { text: string; citations: Citation[] } {\r\n const citations = this.parse(text)\r\n if (citations.length === 0) {\r\n return { text, citations: [] }\r\n }\r\n\r\n let cleaned = ''\r\n let lastEnd = 0\r\n for (const c of citations) {\r\n cleaned += text.slice(lastEnd, c.start)\r\n lastEnd = c.end\r\n }\r\n cleaned += text.slice(lastEnd)\r\n\r\n return { text: cleaned.trim(), citations }\r\n }\r\n\r\n /**\r\n * Replace citation markers with custom formatter output.\r\n *\r\n * @param text — source text\r\n * @param format — callback receiving citation index, returns replacement string\r\n */\r\n replace(text: string, format: (index: number) => string): string {\r\n return text.replace(CitationParser.MARKER_RE, (_match, num) => format(parseInt(num, 10)))\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// ChunkMatcher\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface KnowledgeChunk {\r\n /** Chunk index (1-based, matching citation numbers) */\r\n index: number\r\n /** Source title or document name */\r\n title: string\r\n /** Chunk text content */\r\n content: string\r\n /** Optional source URL or identifier */\r\n source?: string\r\n /** Relevance score (0–1) */\r\n score?: number\r\n}\r\n\r\nexport interface MatchedChunk extends KnowledgeChunk {\r\n /** Citation markers that reference this chunk */\r\n citedBy: number[]\r\n}\r\n\r\nexport class ChunkMatcher {\r\n /**\r\n * Match parsed citations to a list of knowledge chunks.\r\n *\r\n * @param citations — output from `CitationParser.parse()`\r\n * @param chunks — chunks returned by backend (should be 1-based indexed)\r\n * @returns chunks that were cited, with `citedBy` populated\r\n */\r\n match(citations: Citation[], chunks: KnowledgeChunk[]): MatchedChunk[] {\r\n const citedIndices = new Set(citations.map(c => c.index))\r\n const indexToCitations = new Map<number, number[]>()\r\n\r\n for (const c of citations) {\r\n const arr = indexToCitations.get(c.index) ?? []\r\n arr.push(c.index)\r\n indexToCitations.set(c.index, arr)\r\n }\r\n\r\n const matched: MatchedChunk[] = []\r\n for (const chunk of chunks) {\r\n if (citedIndices.has(chunk.index)) {\r\n matched.push({\r\n ...chunk,\r\n citedBy: indexToCitations.get(chunk.index) ?? [chunk.index],\r\n })\r\n }\r\n }\r\n\r\n // Preserve chunk order\r\n matched.sort((a, b) => a.index - b.index)\r\n return matched\r\n }\r\n\r\n /**\r\n * Build a flat map: citation index → chunk.\r\n *\r\n * @returns Map where key is citation number and value is the matching chunk\r\n */\r\n buildIndexMap(chunks: KnowledgeChunk[]): Map<number, KnowledgeChunk> {\r\n const map = new Map<number, KnowledgeChunk>()\r\n for (const chunk of chunks) {\r\n map.set(chunk.index, chunk)\r\n }\r\n return map\r\n }\r\n\r\n /**\r\n * Find chunks that are NOT cited in the text (orphans).\r\n */\r\n findOrphans(citations: Citation[], chunks: KnowledgeChunk[]): KnowledgeChunk[] {\r\n const cited = new Set(citations.map(c => c.index))\r\n return chunks.filter(c => !cited.has(c.index))\r\n }\r\n}\r\n"],"names":["m","t","step","c","a","b"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/http.ts","../src/state/index.ts","../src/orchestrator/index.ts","../src/knowledge/index.ts","../src/transport/v2/reduce.ts"],"sourcesContent":["/**\r\n * AI Assistant REST HTTP Client\r\n *\r\n * Zero-dependency HTTP client for communicating with the Frost AI backend.\r\n * Automatically unwraps `Result<T>` responses (`{ code, message, data, traceId }`).\r\n * Designed for the core package with no framework dependency.\r\n */\r\n\r\nimport type {\r\n AssistantMessage,\r\n Conversation,\r\n ModelOption,\r\n} from './protocol/types'\r\n\r\ninterface ApiResult<T> {\r\n code: number\r\n message: string\r\n data: T\r\n traceId?: string\r\n}\r\n\r\nexport interface PluginConfig {\r\n systemCode: string\r\n defaultMode: string\r\n themeStrategy: string\r\n themePreset: string\r\n primaryColor: string\r\n defaultModelCode: string\r\n enableFullscreen: boolean\r\n enableDrawer: boolean\r\n enableKnowledge: boolean\r\n enableText2Sql: boolean\r\n rateLimitPerHour: number\r\n}\r\n\r\nexport interface DataSourceItem {\r\n code: string\r\n name: string\r\n type: string\r\n description?: string\r\n}\r\n\r\nexport interface TableInfo {\r\n tableName: string\r\n tableComment?: string\r\n columns?: Array<{\r\n columnName: string\r\n columnType: string\r\n columnComment?: string\r\n sensitive?: boolean\r\n }>\r\n}\r\n\r\nexport class AiHttpError extends Error {\r\n readonly code: number\r\n readonly traceId?: string\r\n\r\n constructor(code: number, message: string, traceId?: string) {\r\n super(message)\r\n this.name = 'AiHttpError'\r\n this.code = code\r\n this.traceId = traceId\r\n }\r\n}\r\n\r\nexport class AiHttpClient {\r\n private readonly baseUrl: string\r\n private readonly headersProvider: () => Record<string, string>\r\n\r\n constructor(baseUrl: string, headersProvider: () => Record<string, string>) {\r\n this.baseUrl = baseUrl.replace(/\\/+$/, '')\r\n this.headersProvider = headersProvider\r\n }\r\n\r\n async getPluginConfig(systemCode: string): Promise<PluginConfig | null> {\r\n const raw = await this.request<Record<string, unknown>>(\r\n 'GET',\r\n `/plugin/config?systemCode=${encodeURIComponent(systemCode)}`,\r\n ).catch(() => null)\r\n\r\n if (!raw) {\r\n return null\r\n }\r\n\r\n return {\r\n systemCode: (raw.systemCode as string) ?? systemCode,\r\n defaultMode: (raw.defaultMode as string) ?? 'floating',\r\n themeStrategy: (raw.themeStrategy as string) ?? 'system',\r\n themePreset: (raw.themePreset as string) ?? 'light',\r\n primaryColor: (raw.primaryColor as string) ?? '#409EFF',\r\n defaultModelCode: (raw.defaultModelCode as string) ?? 'default',\r\n enableFullscreen: Boolean(raw.enableFullscreen ?? true),\r\n enableDrawer: Boolean(raw.enableDrawer ?? true),\r\n enableKnowledge: Boolean(raw.enableKnowledge ?? false),\r\n enableText2Sql: Boolean(raw.enableText2Sql ?? true),\r\n rateLimitPerHour: Number(raw.rateLimitPerHour ?? 100),\r\n }\r\n }\r\n\r\n async listModels(): Promise<ModelOption[]> {\r\n const raw = await this.request<Array<Record<string, unknown>>>('GET', '/models')\r\n\r\n return raw.map((item) => ({\r\n code: (item.code as string) ?? (item.modelCode as string) ?? '',\r\n name: (item.name as string) ?? (item.modelName as string) ?? '',\r\n supportStream: Boolean(item.supportStream ?? true),\r\n supportToolCall: Boolean(item.supportToolCall ?? false),\r\n bestFor: ((item.bestFor as ModelOption['bestFor']) ?? []).filter(Boolean),\r\n maxTokens: typeof item.maxTokens === 'number' ? item.maxTokens : undefined,\r\n })).filter((item) => item.code && item.name)\r\n }\r\n\r\n async createConversation(\r\n systemCode: string,\r\n title?: string,\r\n modelCode?: string,\r\n ): Promise<Conversation> {\r\n return this.request<Conversation>('POST', '/conversations', {\r\n systemCode,\r\n title: title ?? 'New conversation',\r\n modelCode: modelCode ?? 'default',\r\n })\r\n }\r\n\r\n async listConversations(\r\n systemCode: string,\r\n page = 1,\r\n size = 20,\r\n ): Promise<Conversation[]> {\r\n return this.request<Conversation[]>(\r\n 'GET',\r\n `/conversations?systemCode=${encodeURIComponent(systemCode)}&page=${page}&size=${size}`,\r\n )\r\n }\r\n\r\n async getMessages(conversationId: string): Promise<AssistantMessage[]> {\r\n return this.request<AssistantMessage[]>(\r\n 'GET',\r\n `/conversations/${encodeURIComponent(conversationId)}/messages`,\r\n )\r\n }\r\n\r\n async deleteConversation(conversationId: string): Promise<void> {\r\n await this.request<void>(\r\n 'DELETE',\r\n `/conversations/${encodeURIComponent(conversationId)}`,\r\n )\r\n }\r\n\r\n async getSuggestions(systemCode: string, sceneCode?: string): Promise<string[]> {\r\n let path = `/suggestions?systemCode=${encodeURIComponent(systemCode)}`\r\n if (sceneCode) {\r\n path += `&sceneCode=${encodeURIComponent(sceneCode)}`\r\n }\r\n return this.request<string[]>('GET', path)\r\n }\r\n\r\n async confirmAction(actionId: string, confirm: boolean): Promise<void> {\r\n await this.request<void>('POST', '/actions/confirm', {\r\n actionId,\r\n confirm,\r\n })\r\n }\r\n\r\n async listDataSources(): Promise<DataSourceItem[]> {\r\n const raw = await this.request<Array<Record<string, unknown>>>('GET', '/data-sources')\r\n\r\n return raw.map((item) => ({\r\n code: (item.code as string) ?? (item.sourceCode as string) ?? '',\r\n name: (item.name as string) ?? (item.sourceName as string) ?? '',\r\n type: (item.type as string) ?? (item.dbType as string) ?? '',\r\n description: item.description as string | undefined,\r\n })).filter((item) => item.code && item.name)\r\n }\r\n\r\n async listTables(dataSourceCode: string): Promise<TableInfo[]> {\r\n const raw = await this.request<Array<Record<string, unknown>>>(\r\n 'GET',\r\n `/data-sources/${encodeURIComponent(dataSourceCode)}/tables`,\r\n )\r\n\r\n return raw.map((item) => ({\r\n tableName: (item.tableName as string) ?? '',\r\n tableComment:\r\n (item.tableComment as string)\r\n ?? (item.tableAlias as string)\r\n ?? (item.description as string)\r\n ?? undefined,\r\n columns: Array.isArray(item.columns) ? item.columns as TableInfo['columns'] : undefined,\r\n })).filter((item) => item.tableName)\r\n }\r\n\r\n async submitFeedback(\r\n messageId: string,\r\n rating: number,\r\n comment?: string,\r\n ): Promise<void> {\r\n await this.request<void>('POST', '/feedback', {\r\n messageId,\r\n rating,\r\n comment,\r\n })\r\n }\r\n\r\n async health(): Promise<{ status: string; service: string }> {\r\n const healthUrl = this.baseUrl.endsWith('/api/ai')\r\n ? `${this.baseUrl.slice(0, -'/api/ai'.length)}/actuator/health`\r\n : `${this.baseUrl}/health`\r\n\r\n const res = await fetch(healthUrl, {\r\n method: 'GET',\r\n headers: this.headersProvider(),\r\n })\r\n\r\n if (!res.ok) {\r\n throw new AiHttpError(res.status, `HTTP ${res.status}: ${res.statusText}`)\r\n }\r\n\r\n const json = await res.json() as ApiResult<{ status: string; service: string }> | { status: string }\r\n if ('code' in json) {\r\n if (json.code !== 200) {\r\n throw new AiHttpError(json.code, json.message ?? 'Unknown API error', json.traceId)\r\n }\r\n return json.data\r\n }\r\n\r\n return {\r\n status: json.status,\r\n service: 'ai-gateway',\r\n }\r\n }\r\n\r\n private async request<T>(\r\n method: string,\r\n path: string,\r\n body?: unknown,\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`\r\n const headers = {\r\n 'Content-Type': 'application/json',\r\n ...this.headersProvider(),\r\n }\r\n\r\n const init: RequestInit = {\r\n method,\r\n headers,\r\n }\r\n\r\n if (body !== undefined && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {\r\n init.body = JSON.stringify(body)\r\n }\r\n\r\n const res = await fetch(url, init)\r\n if (!res.ok) {\r\n throw new AiHttpError(res.status, `HTTP ${res.status}: ${res.statusText}`)\r\n }\r\n\r\n if (res.status === 204 || method === 'DELETE') {\r\n return undefined as T\r\n }\r\n\r\n const json = await res.json() as ApiResult<T>\r\n if (json.code !== undefined && json.code !== 200) {\r\n throw new AiHttpError(\r\n json.code,\r\n json.message ?? 'Unknown API error',\r\n json.traceId,\r\n )\r\n }\r\n\r\n return json.data as T\r\n }\r\n}\r\n","/**\r\n * Pure TypeScript state management for AI Assistant Core\r\n *\r\n * No Vue / React / Pinia dependency.\r\n * Can be wrapped by any framework's reactive system.\r\n */\r\n\r\nimport type {\r\n AiOpenMode,\r\n AiThemeMode,\r\n AssistantMessage,\r\n Conversation,\r\n MessageStatus,\r\n ToolStep,\r\n} from '../protocol'\r\n\r\n// ---------------------------------------------------------------------------\r\n// State shape\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface AssistantState {\r\n /** UI visibility */\r\n visible: boolean\r\n /** Current display mode */\r\n mode: AiOpenMode\r\n /** Previous mode before switch (for back-navigation) */\r\n previousMode: AiOpenMode | null\r\n /** Floating window position (px) */\r\n position: { x: number; y: number }\r\n /** Floating window size (px) */\r\n size: { width: number; height: number }\r\n /** Business system code */\r\n systemCode: string\r\n /** Selected model code */\r\n modelCode: string\r\n /** Current conversation id */\r\n currentConversationId: string | null\r\n /** All loaded conversations */\r\n conversations: Conversation[]\r\n /** Messages keyed by conversation id */\r\n messagesByConversation: Record<string, AssistantMessage[]>\r\n /** Tool steps keyed by message id */\r\n toolStepsByMessage: Record<string, ToolStep[]>\r\n /** Stream connection status */\r\n streamStatus: 'idle' | 'connecting' | 'streaming' | 'reconnecting' | 'closed' | 'error'\r\n /** Last received sequence number (for ack / resume) */\r\n lastSeq: number\r\n /** Last heartbeat timestamp */\r\n lastHeartbeatAt: number\r\n /** Reconnect attempt counter */\r\n reconnectAttempt: number\r\n /** Theme mode */\r\n themeMode: AiThemeMode\r\n /** Primary color */\r\n primaryColor: string\r\n /** Whether an error toast is currently shown */\r\n hasError: boolean\r\n /** Last error message (transient) */\r\n lastError: string | null\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Action types (discriminated union for reducer)\r\n// ---------------------------------------------------------------------------\r\n\r\nexport type StateAction =\r\n | { type: 'OPEN'; mode?: AiOpenMode }\r\n | { type: 'CLOSE' }\r\n | { type: 'TOGGLE' }\r\n | { type: 'SWITCH_MODE'; mode: AiOpenMode }\r\n | { type: 'SET_POSITION'; x: number; y: number }\r\n | { type: 'SET_SIZE'; width: number; height: number }\r\n | { type: 'SET_SYSTEM_CODE'; systemCode: string }\r\n | { type: 'SET_MODEL_CODE'; modelCode: string }\r\n | { type: 'SET_CONVERSATION'; id: string | null }\r\n | { type: 'ADD_CONVERSATION'; conversation: Conversation }\r\n | { type: 'SET_CONVERSATIONS'; conversations: Conversation[] }\r\n | { type: 'APPEND_MESSAGE'; conversationId: string; message: AssistantMessage }\r\n | { type: 'APPEND_DELTA'; conversationId: string; messageId: string; delta: string }\r\n | { type: 'UPDATE_MESSAGE_STATUS'; conversationId: string; messageId: string; status: MessageStatus }\r\n | { type: 'SET_MESSAGES'; conversationId: string; messages: AssistantMessage[] }\r\n | { type: 'APPEND_TOOL_STEP'; messageId: string; step: ToolStep }\r\n | { type: 'UPDATE_TOOL_STEP'; messageId: string; stepId: string; patch: Partial<ToolStep> }\r\n | { type: 'SET_STREAM_STATUS'; status: AssistantState['streamStatus'] }\r\n | { type: 'SET_LAST_SEQ'; seq: number }\r\n | { type: 'SET_HEARTBEAT'; ts: number }\r\n | { type: 'INCREMENT_RECONNECT' }\r\n | { type: 'RESET_RECONNECT' }\r\n | { type: 'SET_THEME'; mode: AiThemeMode }\r\n | { type: 'SET_PRIMARY_COLOR'; color: string }\r\n | { type: 'SET_ERROR'; error: string | null }\r\n | { type: 'HYDRATE'; state: Partial<AssistantState> }\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function createInitialState(overrides?: Partial<AssistantState>): AssistantState {\r\n return {\r\n visible: false,\r\n mode: 'floating',\r\n previousMode: null,\r\n position: { x: 0, y: 0 },\r\n size: { width: 420, height: 600 },\r\n systemCode: '',\r\n modelCode: '',\r\n currentConversationId: null,\r\n conversations: [],\r\n messagesByConversation: {},\r\n toolStepsByMessage: {},\r\n streamStatus: 'idle',\r\n lastSeq: 0,\r\n lastHeartbeatAt: 0,\r\n reconnectAttempt: 0,\r\n themeMode: 'system',\r\n primaryColor: '#1677ff',\r\n hasError: false,\r\n lastError: null,\r\n ...overrides,\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Reducer (pure function)\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function reducer(state: AssistantState, action: StateAction): AssistantState {\r\n switch (action.type) {\r\n case 'OPEN':\r\n return {\r\n ...state,\r\n visible: true,\r\n mode: action.mode ?? state.mode,\r\n }\r\n\r\n case 'CLOSE':\r\n return { ...state, visible: false }\r\n\r\n case 'TOGGLE':\r\n return { ...state, visible: !state.visible }\r\n\r\n case 'SWITCH_MODE': {\r\n return {\r\n ...state,\r\n previousMode: state.mode,\r\n mode: action.mode,\r\n }\r\n }\r\n\r\n case 'SET_POSITION':\r\n return {\r\n ...state,\r\n position: { x: action.x, y: action.y },\r\n }\r\n\r\n case 'SET_SIZE':\r\n return {\r\n ...state,\r\n size: { width: action.width, height: action.height },\r\n }\r\n\r\n case 'SET_SYSTEM_CODE':\r\n return { ...state, systemCode: action.systemCode }\r\n\r\n case 'SET_MODEL_CODE':\r\n return { ...state, modelCode: action.modelCode }\r\n\r\n case 'SET_CONVERSATION':\r\n return { ...state, currentConversationId: action.id }\r\n\r\n case 'ADD_CONVERSATION': {\r\n const next = [action.conversation, ...state.conversations]\r\n return { ...state, conversations: next }\r\n }\r\n\r\n case 'SET_CONVERSATIONS':\r\n return { ...state, conversations: action.conversations }\r\n\r\n case 'APPEND_MESSAGE': {\r\n const list = state.messagesByConversation[action.conversationId] ?? []\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: [...list, action.message],\r\n },\r\n }\r\n }\r\n\r\n case 'APPEND_DELTA': {\r\n const list = state.messagesByConversation[action.conversationId]\r\n if (!list) return state\r\n const idx = list.findIndex(m => m.id === action.messageId)\r\n if (idx === -1) return state\r\n const next = list.slice()\r\n next[idx] = { ...next[idx], content: next[idx].content + action.delta }\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: next,\r\n },\r\n }\r\n }\r\n\r\n case 'UPDATE_MESSAGE_STATUS': {\r\n const list = state.messagesByConversation[action.conversationId]\r\n if (!list) return state\r\n const idx = list.findIndex(m => m.id === action.messageId)\r\n if (idx === -1) return state\r\n const next = list.slice()\r\n const msg = next[idx]\r\n next[idx] = {\r\n ...msg,\r\n status: action.status,\r\n finishedAt:\r\n action.status === 'success' || action.status === 'failed'\r\n ? new Date().toISOString()\r\n : msg.finishedAt,\r\n }\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: next,\r\n },\r\n }\r\n }\r\n\r\n case 'SET_MESSAGES':\r\n return {\r\n ...state,\r\n messagesByConversation: {\r\n ...state.messagesByConversation,\r\n [action.conversationId]: action.messages,\r\n },\r\n }\r\n\r\n case 'APPEND_TOOL_STEP': {\r\n const steps = state.toolStepsByMessage[action.messageId] ?? []\r\n return {\r\n ...state,\r\n toolStepsByMessage: {\r\n ...state.toolStepsByMessage,\r\n [action.messageId]: [...steps, action.step],\r\n },\r\n }\r\n }\r\n\r\n case 'UPDATE_TOOL_STEP': {\r\n const steps = state.toolStepsByMessage[action.messageId]\r\n if (!steps) return state\r\n const idx = steps.findIndex(s => s.stepId === action.stepId)\r\n if (idx === -1) return state\r\n const next = steps.slice()\r\n next[idx] = { ...next[idx], ...action.patch }\r\n return {\r\n ...state,\r\n toolStepsByMessage: {\r\n ...state.toolStepsByMessage,\r\n [action.messageId]: next,\r\n },\r\n }\r\n }\r\n\r\n case 'SET_STREAM_STATUS':\r\n return { ...state, streamStatus: action.status }\r\n\r\n case 'SET_LAST_SEQ':\r\n return { ...state, lastSeq: action.seq }\r\n\r\n case 'SET_HEARTBEAT':\r\n return { ...state, lastHeartbeatAt: action.ts }\r\n\r\n case 'INCREMENT_RECONNECT':\r\n return { ...state, reconnectAttempt: state.reconnectAttempt + 1 }\r\n\r\n case 'RESET_RECONNECT':\r\n return { ...state, reconnectAttempt: 0 }\r\n\r\n case 'SET_THEME':\r\n return { ...state, themeMode: action.mode }\r\n\r\n case 'SET_PRIMARY_COLOR':\r\n return { ...state, primaryColor: action.color }\r\n\r\n case 'SET_ERROR':\r\n return {\r\n ...state,\r\n hasError: action.error !== null,\r\n lastError: action.error,\r\n }\r\n\r\n case 'HYDRATE':\r\n return { ...state, ...action.state }\r\n\r\n default:\r\n return state\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Serialization / Deserialization\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface SerializedState {\r\n version: number\r\n state: Omit<AssistantState, 'streamStatus' | 'lastSeq' | 'lastHeartbeatAt' | 'reconnectAttempt' | 'hasError' | 'lastError'>\r\n}\r\n\r\nconst SERIAL_VERSION = 1\r\n\r\n/** Serialize state to JSON-safe object (excludes transient stream fields). */\r\nexport function serialize(state: AssistantState): SerializedState {\r\n const {\r\n streamStatus,\r\n lastSeq,\r\n lastHeartbeatAt,\r\n reconnectAttempt,\r\n hasError,\r\n lastError,\r\n ...persistable\r\n } = state\r\n void streamStatus\r\n void lastSeq\r\n void lastHeartbeatAt\r\n void reconnectAttempt\r\n void hasError\r\n void lastError\r\n return { version: SERIAL_VERSION, state: persistable as SerializedState['state'] }\r\n}\r\n\r\n/** Deserialize and merge with fresh initial state defaults. */\r\nexport function deserialize(data: unknown): AssistantState | null {\r\n if (!data || typeof data !== 'object') return null\r\n const parsed = data as SerializedState\r\n if (parsed.version !== SERIAL_VERSION) return null\r\n return createInitialState(parsed.state)\r\n}\r\n\r\n/** Convenience: serialize to JSON string. */\r\nexport function serializeToString(state: AssistantState): string {\r\n return JSON.stringify(serialize(state))\r\n}\r\n\r\n/** Convenience: deserialize from JSON string. */\r\nexport function deserializeFromString(json: string): AssistantState | null {\r\n try {\r\n return deserialize(JSON.parse(json))\r\n } catch {\r\n return null\r\n }\r\n}\r\n","/**\r\n * Tool-call orchestrator for AI Assistant Core\r\n *\r\n * ToolRegistry — register / lookup tools\r\n * ToolOrchestrator — execute steps in parallel or serial order\r\n */\r\n\r\nimport type { ToolDefinition, ToolExecutor, ToolStep } from '../protocol'\r\nimport { generateId } from '../utils'\r\n\r\n// ---------------------------------------------------------------------------\r\n// ToolRegistry\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface RegisteredTool {\r\n definition: ToolDefinition\r\n executor: ToolExecutor\r\n}\r\n\r\nexport class ToolRegistry {\r\n private readonly tools = new Map<string, RegisteredTool>()\r\n\r\n /** Register a tool with its definition and executor. */\r\n register(definition: ToolDefinition, executor: ToolExecutor): void {\r\n this.tools.set(definition.name, { definition, executor })\r\n }\r\n\r\n /** Unregister a tool by name. */\r\n unregister(name: string): boolean {\r\n return this.tools.delete(name)\r\n }\r\n\r\n /** Look up a registered tool. */\r\n get(name: string): RegisteredTool | undefined {\r\n return this.tools.get(name)\r\n }\r\n\r\n /** Check whether a tool is registered. */\r\n has(name: string): boolean {\r\n return this.tools.has(name)\r\n }\r\n\r\n /** List all registered tool names. */\r\n list(): string[] {\r\n return Array.from(this.tools.keys())\r\n }\r\n\r\n /** Get all definitions (for sending to LLM). */\r\n getDefinitions(): ToolDefinition[] {\r\n return Array.from(this.tools.values()).map(t => t.definition)\r\n }\r\n\r\n /** Clear all registrations. */\r\n clear(): void {\r\n this.tools.clear()\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// ToolOrchestrator\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface OrchestratorOptions {\r\n registry: ToolRegistry\r\n onStepStart?: (step: ToolStep) => void\r\n onStepProgress?: (stepId: string, percent: number, message?: string) => void\r\n onStepComplete?: (step: ToolStep) => void\r\n onStepError?: (step: ToolStep, error: Error) => void\r\n}\r\n\r\nexport type ExecutionMode = 'parallel' | 'serial'\r\n\r\nexport interface ExecutionPlan {\r\n mode: ExecutionMode\r\n steps: Array<{\r\n toolName: string\r\n args: Record<string, unknown>\r\n title?: string\r\n }>\r\n}\r\n\r\nexport class ToolOrchestrator {\r\n private readonly registry: ToolRegistry\r\n private readonly onStepStart?: (step: ToolStep) => void\r\n private readonly onStepComplete?: (step: ToolStep) => void\r\n private readonly onStepError?: (step: ToolStep, error: Error) => void\r\n\r\n constructor(options: OrchestratorOptions) {\r\n this.registry = options.registry\r\n this.onStepStart = options.onStepStart\r\n this.onStepComplete = options.onStepComplete\r\n this.onStepError = options.onStepError\r\n }\r\n\r\n /**\r\n * Execute a plan of tool steps.\r\n *\r\n * - `serial`: steps run one after another; if one fails, abort the rest.\r\n * - `parallel`: steps run concurrently; all results collected regardless of individual failures.\r\n */\r\n async execute(plan: ExecutionPlan): Promise<ToolStep[]> {\r\n if (plan.mode === 'serial') {\r\n return this.executeSerial(plan.steps)\r\n }\r\n return this.executeParallel(plan.steps)\r\n }\r\n\r\n /** Execute a single tool step. */\r\n async executeSingle(\r\n toolName: string,\r\n args: Record<string, unknown>,\r\n title?: string\r\n ): Promise<ToolStep> {\r\n const registered = this.registry.get(toolName)\r\n if (!registered) {\r\n const step: ToolStep = {\r\n stepId: generateId('step_'),\r\n toolName,\r\n title: title ?? toolName,\r\n status: 'error',\r\n args,\r\n message: `Tool \"${toolName}\" is not registered`,\r\n }\r\n this.onStepError?.(step, new Error(step.message))\r\n return step\r\n }\r\n\r\n const step: ToolStep = {\r\n stepId: generateId('step_'),\r\n toolName,\r\n title: title ?? registered.definition.description ?? toolName,\r\n status: 'running',\r\n args,\r\n }\r\n\r\n this.onStepStart?.(step)\r\n\r\n const startTime = Date.now()\r\n try {\r\n const result = await registered.executor(args)\r\n step.status = 'success'\r\n step.result = result\r\n step.durationMs = Date.now() - startTime\r\n this.onStepComplete?.(step)\r\n return step\r\n } catch (err) {\r\n step.status = 'error'\r\n step.result = err instanceof Error ? err.message : String(err)\r\n step.durationMs = Date.now() - startTime\r\n this.onStepError?.(step, err instanceof Error ? err : new Error(String(err)))\r\n return step\r\n }\r\n }\r\n\r\n private async executeSerial(\r\n steps: ExecutionPlan['steps']\r\n ): Promise<ToolStep[]> {\r\n const results: ToolStep[] = []\r\n for (const s of steps) {\r\n const result = await this.executeSingle(s.toolName, s.args, s.title)\r\n results.push(result)\r\n if (result.status === 'error') {\r\n // Abort remaining serial steps\r\n break\r\n }\r\n }\r\n return results\r\n }\r\n\r\n private async executeParallel(\r\n steps: ExecutionPlan['steps']\r\n ): Promise<ToolStep[]> {\r\n return Promise.all(\r\n steps.map(s => this.executeSingle(s.toolName, s.args, s.title))\r\n )\r\n }\r\n}\r\n","/**\r\n * Knowledge-base citation parser for AI Assistant Core\r\n *\r\n * Parses [1] [2] citation markers in assistant text and\r\n * matches them against content chunks returned by the backend.\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// CitationParser\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface Citation {\r\n /** Raw marker text, e.g. \"[1]\" */\r\n marker: string\r\n /** Numeric index, e.g. 1 */\r\n index: number\r\n /** Start position in the source text */\r\n start: number\r\n /** End position in the source text */\r\n end: number\r\n}\r\n\r\nexport class CitationParser {\r\n /** Regex for citation markers: [1], [12], etc. */\r\n private static readonly MARKER_RE = /\\[(\\d+)\\]/g\r\n\r\n /**\r\n * Extract all citation markers from a text block.\r\n *\r\n * @param text — source text containing [1], [2], … markers\r\n * @returns ordered list of citations with positions\r\n */\r\n parse(text: string): Citation[] {\r\n const citations: Citation[] = []\r\n let match: RegExpExecArray | null\r\n CitationParser.MARKER_RE.lastIndex = 0\r\n while ((match = CitationParser.MARKER_RE.exec(text)) !== null) {\r\n citations.push({\r\n marker: match[0],\r\n index: parseInt(match[1], 10),\r\n start: match.index,\r\n end: match.index + match[0].length,\r\n })\r\n }\r\n return citations\r\n }\r\n\r\n /**\r\n * Strip citation markers from text, returning clean text and a mapping.\r\n *\r\n * @returns `{ text: string, citations: Citation[] }`\r\n */\r\n strip(text: string): { text: string; citations: Citation[] } {\r\n const citations = this.parse(text)\r\n if (citations.length === 0) {\r\n return { text, citations: [] }\r\n }\r\n\r\n let cleaned = ''\r\n let lastEnd = 0\r\n for (const c of citations) {\r\n cleaned += text.slice(lastEnd, c.start)\r\n lastEnd = c.end\r\n }\r\n cleaned += text.slice(lastEnd)\r\n\r\n return { text: cleaned.trim(), citations }\r\n }\r\n\r\n /**\r\n * Replace citation markers with custom formatter output.\r\n *\r\n * @param text — source text\r\n * @param format — callback receiving citation index, returns replacement string\r\n */\r\n replace(text: string, format: (index: number) => string): string {\r\n return text.replace(CitationParser.MARKER_RE, (_match, num) => format(parseInt(num, 10)))\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// ChunkMatcher\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface KnowledgeChunk {\r\n /** Chunk index (1-based, matching citation numbers) */\r\n index: number\r\n /** Source title or document name */\r\n title: string\r\n /** Chunk text content */\r\n content: string\r\n /** Optional source URL or identifier */\r\n source?: string\r\n /** Relevance score (0–1) */\r\n score?: number\r\n}\r\n\r\nexport interface MatchedChunk extends KnowledgeChunk {\r\n /** Citation markers that reference this chunk */\r\n citedBy: number[]\r\n}\r\n\r\nexport class ChunkMatcher {\r\n /**\r\n * Match parsed citations to a list of knowledge chunks.\r\n *\r\n * @param citations — output from `CitationParser.parse()`\r\n * @param chunks — chunks returned by backend (should be 1-based indexed)\r\n * @returns chunks that were cited, with `citedBy` populated\r\n */\r\n match(citations: Citation[], chunks: KnowledgeChunk[]): MatchedChunk[] {\r\n const citedIndices = new Set(citations.map(c => c.index))\r\n const indexToCitations = new Map<number, number[]>()\r\n\r\n for (const c of citations) {\r\n const arr = indexToCitations.get(c.index) ?? []\r\n arr.push(c.index)\r\n indexToCitations.set(c.index, arr)\r\n }\r\n\r\n const matched: MatchedChunk[] = []\r\n for (const chunk of chunks) {\r\n if (citedIndices.has(chunk.index)) {\r\n matched.push({\r\n ...chunk,\r\n citedBy: indexToCitations.get(chunk.index) ?? [chunk.index],\r\n })\r\n }\r\n }\r\n\r\n // Preserve chunk order\r\n matched.sort((a, b) => a.index - b.index)\r\n return matched\r\n }\r\n\r\n /**\r\n * Build a flat map: citation index → chunk.\r\n *\r\n * @returns Map where key is citation number and value is the matching chunk\r\n */\r\n buildIndexMap(chunks: KnowledgeChunk[]): Map<number, KnowledgeChunk> {\r\n const map = new Map<number, KnowledgeChunk>()\r\n for (const chunk of chunks) {\r\n map.set(chunk.index, chunk)\r\n }\r\n return map\r\n }\r\n\r\n /**\r\n * Find chunks that are NOT cited in the text (orphans).\r\n */\r\n findOrphans(citations: Citation[], chunks: KnowledgeChunk[]): KnowledgeChunk[] {\r\n const cited = new Set(citations.map(c => c.index))\r\n return chunks.filter(c => !cited.has(c.index))\r\n }\r\n}\r\n","/**\n * v2 stream reducer — pure, deterministic accumulator→snapshot fold.\n *\n * Designed for Phase-1 Vue stores to consume instead of the legacy `adaptEvent`.\n * Pure TypeScript, zero Vue / framework dependency (CLAUDE.md §3.1 red line).\n *\n * ## Seq / ordering policy\n * - Each event carries a globally monotonic `seq` cursor.\n * - On `run.start` the current message's `lastSeq` resets to `event.seq - 1` so\n * all subsequent events for this run are accepted.\n * - For all other events: if `event.seq <= state.lastSeq`, the event is SKIPPED\n * (duplicate / out-of-order replay already seen).\n * - `lastSeq` is updated to `event.seq` after every accepted event.\n * - Delta accumulation is idempotent given strict seq ordering; `*.end` events\n * are authoritative no-op finalizers (they carry no new content).\n * - Unknown `type` values are silently ignored (forward-compat; never throw).\n *\n * ## Immutability contract\n * `reduce` returns a new `ReduceState` object. Top-level arrays (messages, parts)\n * are replaced on mutation so shallow comparison works in Vue reactive systems.\n * Inner objects (e.g. `TextPart`) are also replaced on mutation.\n */\n\nimport type {\n StreamEvent,\n Usage,\n FinishReason,\n ToolOutput,\n ToolStatus,\n RiskLevel,\n JsonPatchOp,\n CardData,\n CardKind,\n} from '../../protocol/v2'\n\n// ---------------------------------------------------------------------------\n// Snapshot types (public API)\n// ---------------------------------------------------------------------------\n\n/** Status of an assistant message lifetime (v2 reducer). */\nexport type RunStatus = 'streaming' | 'complete' | 'error'\n\n/** Status of a tool call across its state machine. */\nexport type ToolPartStatus =\n | 'pending'\n | 'input-streaming'\n | 'input-ready'\n | 'executing'\n | 'output-available'\n | 'output-error'\n\n/** A streamed text block (main reply or continuation). */\nexport interface TextPart {\n kind: 'text'\n partId: string\n text: string\n}\n\n/** Chain-of-thought reasoning block (optional; default not rendered). */\nexport interface ReasoningPart {\n kind: 'reasoning'\n partId: string\n text: string\n}\n\n/** A tool invocation with full lifecycle state. */\nexport interface ToolPart {\n kind: 'tool'\n toolCallId: string\n toolName: string\n status: ToolPartStatus\n /** Accumulated raw JSON string of the input (from `tool.input.delta`). */\n inputRaw?: string\n /** Authoritative parsed input (from `tool.input`). */\n input?: Record<string, string | number | boolean | null>\n output?: ToolOutput\n outputStatus?: ToolStatus\n error?: string\n}\n\n/** A rich content card (sql / table / chart / metric / …). */\nexport interface CardPart {\n kind: 'card'\n id: string\n cardKind: CardKind\n data: CardData\n transient?: boolean\n status?: string\n}\n\n/** A write-action pending 二次确认. */\nexport interface ActionPart {\n kind: 'action'\n actionId: string\n title: string\n summary?: string\n riskLevel: RiskLevel\n params: Record<string, string | number | boolean | null>\n}\n\n/** A clarification request asking the user to choose or answer. */\nexport interface ClarifyPart {\n kind: 'clarify'\n question: string\n options?: string[]\n}\n\n/** Discriminated union of all renderable parts of an assistant turn. */\nexport type Part = TextPart | ReasoningPart | ToolPart | CardPart | ActionPart | ClarifyPart\n\n/**\n * Complete snapshot of a single assistant message at a point in time.\n * Parts are ordered by the `seq` of their originating start event.\n */\nexport interface MessageSnapshot {\n messageId: string\n conversationId: string\n status: RunStatus\n parts: Part[]\n usage?: Usage\n finishReason?: FinishReason\n /** Wall-clock latency reported by the backend on `run.finish`. */\n latencyMs?: number\n /** Timestamp (ms) when `run.start` was received. */\n startedAt: number\n}\n\n// ---------------------------------------------------------------------------\n// Index maps (kept inside state for O(1) lookups)\n// ---------------------------------------------------------------------------\n\n/** Internal indexes for the current (last) message. */\ninterface MessageIndexes {\n /** partId → index in `parts` for text/reasoning parts */\n byPartId: Map<string, number>\n /** toolCallId → index in `parts` for tool parts */\n byToolCallId: Map<string, number>\n /** card.id → index in `parts` for card parts */\n byCardId: Map<string, number>\n}\n\n/**\n * Accumulator state for `reduce`. Plain / serialisable (Maps are the only\n * non-JSON-native field; callers that need JSON-round-trip should serialise\n * them separately).\n */\nexport interface ReduceState {\n /** Ordered list of assistant messages produced so far. */\n messages: MessageSnapshot[]\n /** Last `seq` accepted (used for duplicate/OOO filtering). */\n lastSeq: number\n /**\n * Internal indexes for the current (last) message.\n * Replaced whenever the active message changes.\n * @internal — Vue stores should not depend on this directly.\n */\n _idx: MessageIndexes\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction makeIndexes(): MessageIndexes {\n return {\n byPartId: new Map(),\n byToolCallId: new Map(),\n byCardId: new Map(),\n }\n}\n\n/** Return a shallow-cloned state with `messages` array replaced. */\nfunction withMessages(state: ReduceState, messages: MessageSnapshot[]): ReduceState {\n return { ...state, messages }\n}\n\n/** Replace the last message in the array. */\nfunction replaceLast(messages: MessageSnapshot[], next: MessageSnapshot): MessageSnapshot[] {\n if (messages.length === 0) return messages\n return [...messages.slice(0, -1), next]\n}\n\n/** Return the last message, or undefined. */\nfunction lastMsg(state: ReduceState): MessageSnapshot | undefined {\n return state.messages[state.messages.length - 1]\n}\n\n/** Replace a part at `index` in the parts array. */\nfunction replacePart(parts: Part[], index: number, next: Part): Part[] {\n const arr = [...parts]\n arr[index] = next\n return arr\n}\n\n/**\n * Apply a minimal subset of RFC 6902 JSON Patch (add / remove / replace) to a\n * plain object. Path must be a single-level `/key` reference. Nested paths and\n * arrays are ignored silently (forward-compat).\n */\nfunction applyPatch(\n target: Record<string, unknown>,\n ops: JsonPatchOp[],\n): Record<string, unknown> {\n let result = { ...target }\n for (const op of ops) {\n // Only handle single-level paths: \"/key\"\n const match = /^\\/([^/]+)$/.exec(op.path)\n if (!match) continue\n const key = match[1]\n if (op.op === 'remove') {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { [key]: _removed, ...rest } = result\n result = rest\n } else if (op.op === 'add' || op.op === 'replace') {\n result = { ...result, [key]: op.value }\n }\n }\n return result\n}\n\n// ---------------------------------------------------------------------------\n// initialState\n// ---------------------------------------------------------------------------\n\n/** Factory for a blank accumulator. */\nexport function initialState(): ReduceState {\n return {\n messages: [],\n lastSeq: 0,\n _idx: makeIndexes(),\n }\n}\n\n// ---------------------------------------------------------------------------\n// reduce\n// ---------------------------------------------------------------------------\n\n/**\n * Pure fold: given the current accumulator state and one v2 `StreamEvent`,\n * return the next state. Never mutates `state`. Unknown event types are\n * ignored silently.\n */\nexport function reduce(state: ReduceState, event: StreamEvent): ReduceState {\n // Duplicate / out-of-order guard (except run.start which resets the cursor)\n if (event.type !== 'run.start' && event.seq <= state.lastSeq) {\n return state\n }\n\n // Advance seq (will be done for every accepted event below)\n const nextSeq = event.seq\n\n // Shorthand: get the current message and its parts\n const msg = lastMsg(state)\n\n switch (event.type) {\n // -------------------------------------------------------------------------\n // run lifecycle\n // -------------------------------------------------------------------------\n case 'run.start': {\n const newMsg: MessageSnapshot = {\n messageId: event.messageId,\n conversationId: event.conversationId,\n status: 'streaming',\n parts: [],\n startedAt: Date.now(),\n }\n return {\n messages: [...state.messages, newMsg],\n lastSeq: nextSeq,\n _idx: makeIndexes(),\n }\n }\n\n case 'run.finish': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const finished: MessageSnapshot = {\n ...msg,\n status: 'complete',\n usage: event.usage,\n finishReason: event.reason,\n latencyMs: event.latencyMs,\n }\n return {\n ...withMessages(state, replaceLast(state.messages, finished)),\n lastSeq: nextSeq,\n }\n }\n\n case 'run.error': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const errored: MessageSnapshot = {\n ...msg,\n status: 'error',\n }\n return {\n ...withMessages(state, replaceLast(state.messages, errored)),\n lastSeq: nextSeq,\n }\n }\n\n // -------------------------------------------------------------------------\n // text block\n // -------------------------------------------------------------------------\n case 'text.start': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = msg.parts.length\n const newPart: TextPart = { kind: 'text', partId: event.partId, text: '' }\n const nextIdx = { ...state._idx, byPartId: new Map(state._idx.byPartId) }\n nextIdx.byPartId.set(event.partId, idx)\n const nextMsg: MessageSnapshot = { ...msg, parts: [...msg.parts, newPart] }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n _idx: nextIdx,\n }\n }\n\n case 'text.delta': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byPartId.get(event.partId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as TextPart\n const updated: TextPart = { ...part, text: part.text + event.delta }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n case 'text.end': {\n // Authoritative no-op finalizer — just advance seq\n return { ...state, lastSeq: nextSeq }\n }\n\n // -------------------------------------------------------------------------\n // reasoning block\n // -------------------------------------------------------------------------\n case 'reasoning.start': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = msg.parts.length\n const newPart: ReasoningPart = { kind: 'reasoning', partId: event.partId, text: '' }\n const nextIdx = { ...state._idx, byPartId: new Map(state._idx.byPartId) }\n nextIdx.byPartId.set(event.partId, idx)\n const nextMsg: MessageSnapshot = { ...msg, parts: [...msg.parts, newPart] }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n _idx: nextIdx,\n }\n }\n\n case 'reasoning.delta': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byPartId.get(event.partId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as ReasoningPart\n const updated: ReasoningPart = { ...part, text: part.text + event.delta }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n case 'reasoning.end': {\n // Authoritative no-op finalizer — just advance seq\n return { ...state, lastSeq: nextSeq }\n }\n\n // -------------------------------------------------------------------------\n // tool-call state machine\n // -------------------------------------------------------------------------\n case 'tool.start': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = msg.parts.length\n const newPart: ToolPart = {\n kind: 'tool',\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n status: 'pending',\n }\n const nextIdx = { ...state._idx, byToolCallId: new Map(state._idx.byToolCallId) }\n nextIdx.byToolCallId.set(event.toolCallId, idx)\n const nextMsg: MessageSnapshot = { ...msg, parts: [...msg.parts, newPart] }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n _idx: nextIdx,\n }\n }\n\n case 'tool.input.delta': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byToolCallId.get(event.toolCallId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as ToolPart\n const updated: ToolPart = {\n ...part,\n status: 'input-streaming',\n inputRaw: (part.inputRaw ?? '') + event.delta,\n }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n case 'tool.input': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byToolCallId.get(event.toolCallId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as ToolPart\n const updated: ToolPart = {\n ...part,\n status: 'input-ready',\n input: event.input,\n }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n case 'tool.executing': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byToolCallId.get(event.toolCallId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as ToolPart\n const updated: ToolPart = { ...part, status: 'executing' }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n case 'tool.output': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byToolCallId.get(event.toolCallId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as ToolPart\n const updated: ToolPart = {\n ...part,\n status: event.status === 'output-available' ? 'output-available' : 'output-error',\n output: event.output,\n outputStatus: event.status,\n }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n case 'tool.error': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byToolCallId.get(event.toolCallId)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as ToolPart\n const updated: ToolPart = { ...part, status: 'output-error', error: event.error }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n // -------------------------------------------------------------------------\n // card (upsert by id; later overrides earlier: loading→ready)\n // -------------------------------------------------------------------------\n case 'card': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const existing = state._idx.byCardId.get(event.id)\n const newPart: CardPart = {\n kind: 'card',\n id: event.id,\n cardKind: event.kind,\n data: event.data,\n transient: event.transient,\n status: event.status,\n }\n if (existing !== undefined) {\n // Upsert: replace in place\n const nextMsg: MessageSnapshot = {\n ...msg,\n parts: replacePart(msg.parts, existing, newPart),\n }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n // New card: append\n const idx = msg.parts.length\n const nextIdx = { ...state._idx, byCardId: new Map(state._idx.byCardId) }\n nextIdx.byCardId.set(event.id, idx)\n const nextMsg: MessageSnapshot = { ...msg, parts: [...msg.parts, newPart] }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n _idx: nextIdx,\n }\n }\n\n case 'card.patch': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const idx = state._idx.byCardId.get(event.id)\n if (idx === undefined) return { ...state, lastSeq: nextSeq }\n const part = msg.parts[idx] as CardPart\n // Apply patch to CardData (cast through unknown for type safety)\n const patchedData = applyPatch(\n part.data as unknown as Record<string, unknown>,\n event.patch,\n ) as unknown as CardData\n const updated: CardPart = { ...part, data: patchedData }\n const nextMsg: MessageSnapshot = { ...msg, parts: replacePart(msg.parts, idx, updated) }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n // -------------------------------------------------------------------------\n // action center\n // -------------------------------------------------------------------------\n case 'action.proposed': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const newPart: ActionPart = {\n kind: 'action',\n actionId: event.actionId,\n title: event.title,\n summary: event.summary,\n riskLevel: event.riskLevel,\n params: event.params,\n }\n const nextMsg: MessageSnapshot = { ...msg, parts: [...msg.parts, newPart] }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n // -------------------------------------------------------------------------\n // clarify\n // -------------------------------------------------------------------------\n case 'clarify': {\n if (!msg) return { ...state, lastSeq: nextSeq }\n const newPart: ClarifyPart = {\n kind: 'clarify',\n question: event.question,\n options: event.options,\n }\n const nextMsg: MessageSnapshot = { ...msg, parts: [...msg.parts, newPart] }\n return {\n ...withMessages(state, replaceLast(state.messages, nextMsg)),\n lastSeq: nextSeq,\n }\n }\n\n // -------------------------------------------------------------------------\n // Forward-compat: unknown event types are silently ignored (never throw)\n // -------------------------------------------------------------------------\n default: {\n // TypeScript exhaustiveness: this branch is unreachable with known events,\n // but at runtime unknown future types fall through safely.\n return { ...state, lastSeq: nextSeq }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// reduceAll\n// ---------------------------------------------------------------------------\n\n/**\n * Convenience fold: reduce an entire ordered sequence of events from scratch.\n * Equivalent to `events.reduce(reduce, initialState())`.\n */\nexport function reduceAll(events: StreamEvent[]): ReduceState {\n return events.reduce(reduce, initialState())\n}\n"],"names":["m","t","step","c","a","b","nextMsg"],"mappings":"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"}