@emseepea/testing 0.26.13 → 0.26.14

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/README.md CHANGED
@@ -109,6 +109,14 @@ argument correctness, persisted effects, response meaning, or recovery from an
109
109
  error. Keep an exact assertion when order, count, and arguments are
110
110
  deterministic, and add the separate assertions your application outcome needs.
111
111
 
112
+ Each turn exposes `assistantMessages`, an immutable array of visible native
113
+ Claude messages for each trial, in event order. Other providers currently return
114
+ empty arrays. These messages may include the final message; `responses` and
115
+ response assertions continue to use the separate terminal result.
116
+
117
+ Saved evidence and meaning-judge history retain these messages without hidden
118
+ reasoning. Earlier text does not satisfy an assertion about the final response.
119
+
112
120
  Each turn also exposes `toolOutcomes`, aligned by trial and call order with
113
121
  `toolCalls`. Each outcome is a read-only snapshot of what the model saw. It
114
122
  contains only `name`, `arguments`, the model-visible `result`, and `isError`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emseepea/testing",
3
- "version": "0.26.13",
3
+ "version": "0.26.14",
4
4
  "description": "MCP integration and semantic testing helpers",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -190,6 +190,12 @@ export function parseNativeClaudeEvents(stdout, advertisedTools, requireInit = f
190
190
  }
191
191
  return {
192
192
  answer: result.result,
193
+ assistantMessages: events.flatMap(({ type, message }) => {
194
+ if (type !== "assistant" || !Array.isArray(message?.content)
195
+ || (message.role !== undefined && message.role !== "assistant")) return [];
196
+ const text = message.content.filter((block) => block.type === "text" && typeof block.text === "string");
197
+ return text.length ? [text.map((block) => block.text).join("")] : [];
198
+ }),
193
199
  calls,
194
200
  toolResults: toolUses.map(({ id }) => {
195
201
  const toolResult = toolResults.get(id);
@@ -52,6 +52,9 @@ export interface ResourceOperation {
52
52
  export interface ConversationTurn {
53
53
  readonly resourceOperations: readonly (readonly ResourceOperation[])[];
54
54
  readonly responses: readonly string[];
55
+ /** Ordered native Claude visible messages by trial. Other providers currently return empty arrays.
56
+ * May include the final message; responses remains the separate terminal result. Excludes hidden reasoning. */
57
+ readonly assistantMessages: readonly (readonly string[])[];
55
58
  readonly toolCalls: readonly (readonly ToolCall[])[];
56
59
  readonly toolOutcomes: readonly (readonly ToolOutcome[])[];
57
60
  readonly elicitations: readonly (readonly ElicitationEvidence[])[];
package/semantic/test.mjs CHANGED
@@ -148,6 +148,7 @@ export async function createConversation(testContext, options) {
148
148
  toolCalls: recordedToolCalls,
149
149
  resourceOperations: answer.resourceOperations ?? [],
150
150
  assistant: answer.answer,
151
+ ...(answer.assistantMessages ? { assistantMessages: answer.assistantMessages } : {}),
151
152
  });
152
153
  const record = {
153
154
  turn: trial.record.turns.length + 1,
@@ -155,6 +156,10 @@ export async function createConversation(testContext, options) {
155
156
  interactionMode: "native-mcp",
156
157
  prompt,
157
158
  response: answer.answer,
159
+ ...(answer.assistantMessages ? {
160
+ assistantMessages: answer.assistantMessages,
161
+ assistantMessagesSha256: hash(JSON.stringify(answer.assistantMessages)),
162
+ } : {}),
158
163
  elicitations: answer.elicitations,
159
164
  toolCalls: recordedToolCalls,
160
165
  resourceOperations: answer.resourceOperations ?? [],
@@ -213,6 +218,7 @@ export async function createConversation(testContext, options) {
213
218
  }
214
219
  return Object.freeze({
215
220
  responses: Object.freeze(trials.map(({ answer }) => answer)),
221
+ assistantMessages: immutableSnapshot(trials.map(({ record }) => record.assistantMessages ?? [])),
216
222
  toolCalls: Object.freeze(trials.map(({ calls }) => Object.freeze(calls))),
217
223
  toolOutcomes: Object.freeze(trials.map(({ record }) => immutableSnapshot(record.toolCalls.map(
218
224
  ({ name, arguments: args, result, isError }) => ({ name, arguments: args, result, isError }),