@meistrari/chat-nuxt 4.5.1-rc.1 → 4.5.1-rc.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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "4.5.1-rc.1",
4
+ "version": "4.5.1-rc.3",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -7,12 +7,12 @@ export function createMessagePartsAccumulator(runId = null) {
7
7
  }
8
8
  export function applyMessagePartsEvent(accumulator, input) {
9
9
  if (input.harness !== "lightweight" && accumulator.lightweight?.runId !== input.runId)
10
- return { text: accumulator.lightweight?.text ?? "", thinking: accumulator.lightweight?.thinking ?? "", changed: false };
10
+ return { text: accumulator.lightweight?.stepText ?? "", thinking: accumulator.lightweight?.thinking ?? "", changed: false };
11
11
  if (accumulator.lightweight?.runId !== input.runId)
12
12
  accumulator.lightweight = createLightweightTurn(input.runId, input.sessionId ?? "");
13
13
  accumulator.runId = input.runId;
14
14
  const changed = applyLightweightPart(accumulator.lightweight, input.event, input.deltaSeq, input.timestamp ?? 0);
15
- return { text: accumulator.lightweight.text, thinking: accumulator.lightweight.thinking, changed, reasoning: accumulator.lightweight.reasoning, files: accumulator.lightweight.files };
15
+ return { text: accumulator.lightweight.stepText, thinking: accumulator.lightweight.thinking, changed, reasoning: accumulator.lightweight.reasoning, files: accumulator.lightweight.files };
16
16
  }
17
17
  export function useDirectStream(options = {}) {
18
18
  return useDirectStreamWithProtocol({
@@ -3,8 +3,8 @@ import ChatDebugConversationRail from "./chat-debug-conversation-rail.vue";
3
3
  import ChatMessageList from "./chat-message-list.vue";
4
4
  import { provideEmbedConfig } from "../../embed/composables/embed-config";
5
5
  import { createChatDebugCitationsConfig } from "../debug/chat-debug-citations";
6
- import { createReasoningCache, resolveReasoningDisplayMessages } from "../message-reasoning";
7
- import { createChatDebugScenarios } from "../debug/chat-debug-scenarios";
6
+ import { createReasoningCache } from "../message-reasoning";
7
+ import { createChatDebugScenarios, resolveChatDebugDisplayMessages } from "../debug/chat-debug-scenarios";
8
8
  import { useChatDebugDiagnostics, useChatDebugWindowListenerProbe } from "../debug/use-chat-debug-diagnostics";
9
9
  import { formatChatDebugTime as formatTime, useChatDebugPlayback } from "../debug/use-chat-debug-playback";
10
10
  const scenarios = createChatDebugScenarios();
@@ -52,7 +52,7 @@ const { diagnostics, reset: resetDiagnostics, recordFrame } = useChatDebugDiagno
52
52
  });
53
53
  const windowListeners = useChatDebugWindowListenerProbe();
54
54
  const reasoningCache = createReasoningCache();
55
- const displayMessages = computed(() => selectedScenario.value.reasoningFormat === "raw" ? resolveReasoningDisplayMessages(playbackState.value.messages, reasoningCache) : playbackState.value.messages);
55
+ const displayMessages = computed(() => resolveChatDebugDisplayMessages(selectedScenario.value, playbackState.value, reasoningCache));
56
56
  const reasoningCacheEntries = ref(0);
57
57
  watch(displayMessages, () => {
58
58
  reasoningCacheEntries.value = reasoningCache.bySignature.size;
@@ -27,6 +27,7 @@ import { CHAT_PREPARING_STEPS, nextChatPreparingStepDelay } from "../../embed/lo
27
27
  import { usePolling } from "../../shared/composables/polling.js";
28
28
  import { ChatMessageStatus, terminalMessageTransitions, useChatMessageTerminal } from "./chat-message-terminal.js";
29
29
  import { useDirectStream } from "./use-direct-stream.js";
30
+ import { overlayStreamedMessage } from "../stream-overlay.js";
30
31
  import { useOutboundQueue } from "./outbound-queue.js";
31
32
  const POLL_OUTAGE_NOTICE_FAILURES = 5;
32
33
  const POLL_OUTAGE_BUDGET_MS = 6e4;
@@ -219,12 +220,7 @@ export function useChat(options = {}, adapter = {}) {
219
220
  const content = directStream.streamingText.value;
220
221
  const reasoning = directStream.streamingReasoning?.value ?? [];
221
222
  const files = directStream.streamingFiles?.value ?? [];
222
- const overlaid = !messageId || content === null && !reasoning.length && !files.length ? messages.value : messages.value.map((message) => message.id === messageId && (message.status === "pending" || pendingStreamReconciliationIds.value.has(message.id)) ? {
223
- ...message,
224
- content: content === null ? message.content : content,
225
- ...reasoning.length ? { reasoningData: reasoning } : {},
226
- ...files.length ? { files: files.map((file) => ({ ...file })) } : {}
227
- } : message);
223
+ const overlaid = !messageId || content === null && !reasoning.length && !files.length ? messages.value : messages.value.map((message) => message.id === messageId && (message.status === "pending" || pendingStreamReconciliationIds.value.has(message.id)) ? overlayStreamedMessage(message, { content, reasoning, files }) : message);
228
224
  return resolveReasoningDisplayMessages(overlaid, reasoningCache);
229
225
  });
230
226
  const stopCondition = computed(
@@ -1,4 +1,5 @@
1
1
  import type { Conversation, Message } from '../../types/schemas/chat/conversations.js';
2
+ import { type ReasoningCache } from '../message-reasoning.js';
2
3
  export type ChatDebugEventTone = 'neutral' | 'user' | 'assistant' | 'reasoning' | 'tool' | 'error';
3
4
  type ChatDebugEventBase = {
4
5
  id: string;
@@ -20,6 +21,9 @@ export type ChatDebugEvent = ChatDebugEventBase & ({
20
21
  type: 'conversation.switch';
21
22
  conversationId: string;
22
23
  messages: Message[];
24
+ } | {
25
+ type: 'stream.part';
26
+ part: Record<string, unknown>;
23
27
  });
24
28
  /** One switchable conversation of a sidebar fixture: identity plus its full history. */
25
29
  export type ChatDebugConversationFixture = {
@@ -50,17 +54,28 @@ export type ChatDebugScenario = {
50
54
  * like production. Absent means the fixture ships pre-parsed steps.
51
55
  */
52
56
  reasoningFormat?: 'raw';
57
+ /**
58
+ * Harness whose stream adapter turns `stream.part` events into the pending
59
+ * message's text and reasoning, exactly like the embed's direct stream.
60
+ */
61
+ streamHarness?: 'lightweight';
53
62
  };
54
63
  export type ChatDebugPlaybackState = {
55
64
  messages: Message[];
56
65
  loading: boolean;
57
66
  streamingActiveMessageId: string | null;
67
+ streamParts: Record<string, unknown>[];
58
68
  preparingSteps: string[] | null;
59
69
  activeConversationId: string | null;
60
70
  };
61
71
  export declare const EMPTY_CHAT_DEBUG_PLAYBACK_STATE: ChatDebugPlaybackState;
62
72
  export declare function applyChatDebugEvent(state: ChatDebugPlaybackState, event: ChatDebugEvent): ChatDebugPlaybackState;
63
73
  export declare function resolveChatDebugPlayback(scenario: ChatDebugScenario, elapsedMs: number): ChatDebugPlaybackState;
74
+ /**
75
+ * What the stage renders: streamed parts go through the harness's real
76
+ * adapter, and raw reasoning through the production resolution.
77
+ */
78
+ export declare function resolveChatDebugDisplayMessages(scenario: ChatDebugScenario, state: ChatDebugPlaybackState, cache: ReasoningCache): Message[];
64
79
  export declare function countAppliedChatDebugEvents(scenario: ChatDebugScenario, elapsedMs: number): number;
65
80
  export declare function createChatDebugScenarios(baseTime?: number): ChatDebugScenario[];
66
81
  export {};
@@ -4,10 +4,15 @@ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __f
4
4
  var _a;
5
5
  import { CHAT_PREPARING_STEPS } from "../../embed/loading-messages.js";
6
6
  import { createConversationSwitchScenario } from "./chat-debug-switch-scenario.js";
7
+ import { applyLightweightPart, createLightweightTurn } from "../../types/schemas/integrations/lightweight.js";
8
+ import { applyMessagePartsEvent as applyLightweightEvent, createMessagePartsAccumulator as createLightweightAccumulator } from "../../lightweight/messages/composables/use-direct-stream.js";
9
+ import { resolveReasoningDisplayMessages } from "../message-reasoning.js";
10
+ import { overlayStreamedMessage } from "../stream-overlay.js";
7
11
  export const EMPTY_CHAT_DEBUG_PLAYBACK_STATE = {
8
12
  messages: [],
9
13
  loading: false,
10
14
  streamingActiveMessageId: null,
15
+ streamParts: [],
11
16
  preparingSteps: null,
12
17
  activeConversationId: null
13
18
  };
@@ -25,6 +30,7 @@ export function applyChatDebugEvent(state, event2) {
25
30
  messages: event2.messages.map(cloneMessage),
26
31
  loading: false,
27
32
  streamingActiveMessageId: null,
33
+ streamParts: [],
28
34
  preparingSteps: null,
29
35
  activeConversationId: event2.conversationId
30
36
  };
@@ -38,6 +44,8 @@ export function applyChatDebugEvent(state, event2) {
38
44
  preparingSteps
39
45
  };
40
46
  }
47
+ if (event2.type === "stream.part")
48
+ return { ...state, streamParts: [...state.streamParts, event2.part] };
41
49
  if (event2.type === "message.patch") {
42
50
  return {
43
51
  ...state,
@@ -68,6 +76,31 @@ export function resolveChatDebugPlayback(scenario, elapsedMs) {
68
76
  }
69
77
  return state;
70
78
  }
79
+ function overlayLightweightStream(state) {
80
+ if (!state.streamingActiveMessageId || state.streamParts.length === 0)
81
+ return state.messages;
82
+ const accumulator = createLightweightAccumulator();
83
+ let update = { text: "", thinking: "", changed: false };
84
+ state.streamParts.forEach((part, deltaSeq) => {
85
+ update = applyLightweightEvent(accumulator, {
86
+ kind: "message-parts",
87
+ harness: "lightweight",
88
+ sessionId: "debug-session",
89
+ runId: "debug-run",
90
+ deltaSeq,
91
+ event: part
92
+ });
93
+ });
94
+ return state.messages.map((message2) => message2.id === state.streamingActiveMessageId && message2.status === "pending" ? overlayStreamedMessage(message2, {
95
+ content: update.text,
96
+ reasoning: "reasoning" in update ? [...update.reasoning] : [],
97
+ files: "files" in update ? [...update.files] : []
98
+ }) : message2);
99
+ }
100
+ export function resolveChatDebugDisplayMessages(scenario, state, cache) {
101
+ const messages = scenario.streamHarness === "lightweight" ? overlayLightweightStream(state) : state.messages;
102
+ return scenario.reasoningFormat === "raw" ? resolveReasoningDisplayMessages(messages, cache) : messages;
103
+ }
71
104
  export function countAppliedChatDebugEvents(scenario, elapsedMs) {
72
105
  let count = 0;
73
106
  for (const event2 of scenario.events) {
@@ -494,12 +527,48 @@ function sessionWakeOpeningEvents(input) {
494
527
  })
495
528
  ];
496
529
  }
530
+ const LIGHTWEIGHT_THOUGHT_FIRST = "O usu\xE1rio quer que eu pesquise as not\xEDcias de hoje.";
531
+ const LIGHTWEIGHT_INTERIM_TEXT = "Vou usar a skill de not\xEDcias para isso.";
532
+ const LIGHTWEIGHT_THOUGHT_SECOND = "J\xE1 tenho as manchetes do dia. Vou organizar por tema.";
533
+ const LIGHTWEIGHT_ANSWER = [
534
+ "Aqui est\xE3o as not\xEDcias de hoje:",
535
+ "",
536
+ "- **Economia:** o Copom manteve a Selic em 10,50% ao ano.",
537
+ "- **Tecnologia:** o governo publicou a regulamenta\xE7\xE3o do uso de IA no setor p\xFAblico.",
538
+ "- **Esportes:** a sele\xE7\xE3o confirmou os convocados para as Eliminat\xF3rias."
539
+ ].join("\n");
540
+ const LIGHTWEIGHT_STREAM_PARTS = [
541
+ [600, "Step starts", { type: "start-step" }],
542
+ [900, "Reasoning delta", { type: "reasoning-delta", id: "r0", text: LIGHTWEIGHT_THOUGHT_FIRST.slice(0, 30) }],
543
+ [1500, "Reasoning delta", { type: "reasoning-delta", id: "r0", text: LIGHTWEIGHT_THOUGHT_FIRST.slice(30) }],
544
+ [2300, "Text delta", { type: "text-delta", id: "t0", delta: LIGHTWEIGHT_INTERIM_TEXT.slice(0, 28) }],
545
+ [2800, "Text delta", { type: "text-delta", id: "t0", delta: LIGHTWEIGHT_INTERIM_TEXT.slice(28) }],
546
+ [3300, "Skill call", { type: "tool-call", toolCallId: "lightweight-news-skill", toolName: "Skill", input: { skill: "noticias" } }],
547
+ [3300, "Step finishes", { type: "finish-step" }],
548
+ [4300, "Skill result", { type: "tool-result", toolCallId: "lightweight-news-skill", toolName: "Skill", output: "Manchetes de economia, tecnologia e esportes." }],
549
+ [4600, "Step starts", { type: "start-step" }],
550
+ [5e3, "Reasoning delta", { type: "reasoning-delta", id: "r1", text: LIGHTWEIGHT_THOUGHT_SECOND.slice(0, 30) }],
551
+ [5600, "Reasoning delta", { type: "reasoning-delta", id: "r1", text: LIGHTWEIGHT_THOUGHT_SECOND.slice(30) }],
552
+ [6300, "Text delta", { type: "text-delta", id: "t1", delta: LIGHTWEIGHT_ANSWER.slice(0, 90) }],
553
+ [7100, "Text delta", { type: "text-delta", id: "t1", delta: LIGHTWEIGHT_ANSWER.slice(90) }],
554
+ [7500, "Step finishes", { type: "finish-step" }]
555
+ ];
556
+ function lightweightPersistedReasoning() {
557
+ const turn = createLightweightTurn("debug-run", "debug-session");
558
+ LIGHTWEIGHT_STREAM_PARTS.forEach(([, , part], sequence) => applyLightweightPart(turn, part, sequence, 0));
559
+ return turn.reasoning;
560
+ }
497
561
  export function createChatDebugScenarios(baseTime = Date.now()) {
498
562
  const streamingMessage = message(baseTime, 650, {
499
563
  id: "streaming-assistant",
500
564
  role: "assistant",
501
565
  status: "pending"
502
566
  });
567
+ const lightweightMessage = message(baseTime, 0, {
568
+ id: "lightweight-assistant",
569
+ role: "assistant",
570
+ status: "pending"
571
+ });
503
572
  const wakeMessage = message(baseTime, 0, {
504
573
  id: "wake-assistant",
505
574
  role: "assistant",
@@ -693,6 +762,75 @@ export function createChatDebugScenarios(baseTime = Date.now()) {
693
762
  })
694
763
  ]
695
764
  },
765
+ {
766
+ id: "lightweight-stream",
767
+ name: "Lightweight stream",
768
+ intent: "Lightweight parts through the real adapter: each step shows only its own text, like the Claude harness.",
769
+ durationMs: 8600,
770
+ reasoningFormat: "raw",
771
+ streamHarness: "lightweight",
772
+ events: [
773
+ event({
774
+ id: "lightweight-user",
775
+ atMs: 0,
776
+ label: "User message",
777
+ tone: "user",
778
+ type: "message.upsert",
779
+ message: message(baseTime, 0, {
780
+ id: "lightweight-user-message",
781
+ role: "user",
782
+ content: "Quais s\xE3o as not\xEDcias de hoje?"
783
+ })
784
+ }),
785
+ event({
786
+ id: "lightweight-pending",
787
+ atMs: 0,
788
+ label: "Assistant pending",
789
+ tone: "assistant",
790
+ type: "message.upsert",
791
+ message: lightweightMessage
792
+ }),
793
+ event({
794
+ id: "lightweight-stream-open",
795
+ atMs: 300,
796
+ label: "Stream opens",
797
+ tone: "neutral",
798
+ type: "playback.patch",
799
+ patch: { streamingActiveMessageId: lightweightMessage.id }
800
+ }),
801
+ ...LIGHTWEIGHT_STREAM_PARTS.map(([atMs, label, part], index) => event({
802
+ id: `lightweight-part-${index}`,
803
+ atMs,
804
+ label,
805
+ tone: part.type === "tool-call" || part.type === "tool-result" ? "tool" : part.type === "reasoning-delta" ? "reasoning" : "assistant",
806
+ type: "stream.part",
807
+ part
808
+ })),
809
+ event({
810
+ id: "lightweight-complete",
811
+ atMs: 7900,
812
+ label: "Message completed",
813
+ tone: "assistant",
814
+ type: "message.patch",
815
+ messageId: lightweightMessage.id,
816
+ patch: {
817
+ status: "completed",
818
+ content: LIGHTWEIGHT_ANSWER,
819
+ reasoningData: lightweightPersistedReasoning(),
820
+ updatedAt: new Date(baseTime + 7900),
821
+ generationEndedAt: new Date(baseTime + 7900)
822
+ }
823
+ }),
824
+ event({
825
+ id: "lightweight-stream-close",
826
+ atMs: 7900,
827
+ label: "Stream closes",
828
+ tone: "neutral",
829
+ type: "playback.patch",
830
+ patch: { streamingActiveMessageId: null }
831
+ })
832
+ ]
833
+ },
696
834
  {
697
835
  id: "session-wake",
698
836
  name: "Session wake",
@@ -0,0 +1,9 @@
1
+ import type { Message } from '../types/schemas/chat/conversations.js';
2
+ import type { MessageFile } from '../types/schemas/chat/files.js';
3
+ import type { DeepReadonly } from 'vue';
4
+ export type StreamOverlay = {
5
+ content: string | null;
6
+ reasoning: DeepReadonly<unknown[]>;
7
+ files: DeepReadonly<MessageFile[]>;
8
+ };
9
+ export declare function overlayStreamedMessage(message: Message, stream: StreamOverlay): Message;
@@ -0,0 +1,8 @@
1
+ export function overlayStreamedMessage(message, stream) {
2
+ return {
3
+ ...message,
4
+ content: stream.content === null ? message.content : stream.content,
5
+ ...stream.reasoning.length ? { reasoningData: stream.reasoning } : {},
6
+ ...stream.files.length ? { files: stream.files.map((file) => ({ ...file })) } : {}
7
+ };
8
+ }
@@ -6,6 +6,7 @@ export declare function createLightweightTurn(runId: string, sessionId: string):
6
6
  sessionId: string;
7
7
  lastSequence: number;
8
8
  text: string;
9
+ stepText: string;
9
10
  pendingText: string;
10
11
  thinking: string;
11
12
  reasoning: ReasoningItem[];
@@ -57,6 +57,10 @@ export function createLightweightTurn(runId, sessionId) {
57
57
  sessionId,
58
58
  lastSequence: -1,
59
59
  text: '',
60
+ // Text of the current provider step only, the equivalent of the Claude
61
+ // harness's current assistant message: an interim line gives way to the
62
+ // next step instead of prefixing the answer.
63
+ stepText: '',
60
64
  pendingText: '',
61
65
  thinking: '',
62
66
  reasoning: [],
@@ -76,8 +80,16 @@ export function applyLightweightPart(state, part, sequence, timestamp) {
76
80
  return false;
77
81
  state.lastSequence = sequence;
78
82
  const delta = typeof part.delta === 'string' ? part.delta : typeof part.text === 'string' ? part.text : '';
83
+ // Deliberately empties the answer slot until this step's own text arrives,
84
+ // exactly as the Claude harness does at message_start; the finished step's
85
+ // interim line is already in the reasoning timeline.
86
+ if (part.type === 'start-step') {
87
+ state.stepText = '';
88
+ return true;
89
+ }
79
90
  if (part.type === 'text-delta') {
80
91
  state.text += delta;
92
+ state.stepText += delta;
81
93
  state.pendingText += delta;
82
94
  state.files = lightweightFiles([state.toolFiles, state.text]);
83
95
  return true;
@@ -56,6 +56,10 @@ export declare const telaAgentRunPayloadSchema: z.ZodObject<{
56
56
  vaultRef: z.ZodString;
57
57
  filename: z.ZodString;
58
58
  }, z.core.$strip>>>;
59
+ autoMappedFiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
60
+ vaultRef: z.ZodString;
61
+ filename: z.ZodString;
62
+ }, z.core.$strip>>>;
59
63
  }, z.core.$catchall<z.ZodUnknown>>;
60
64
  export type TelaAgentRunPayload = z.infer<typeof telaAgentRunPayloadSchema>;
61
65
  export declare const telaAgentSkillSchema: z.ZodObject<{
@@ -32,6 +32,7 @@ export const telaAgentRunPayloadSchema = z.object({
32
32
  sessionId: z.string().optional(),
33
33
  inputSchema: z.array(telaAgentExecutionInputSchema).optional(),
34
34
  attachments: z.array(telaAgentAttachmentSchema).optional(),
35
+ autoMappedFiles: z.array(telaAgentAttachmentSchema).optional(),
35
36
  }).catchall(z.unknown());
36
37
  export const telaAgentSkillSchema = z.object({
37
38
  name: z.string(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
- "version": "4.5.1-rc.1",
3
+ "version": "4.5.1-rc.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {