@@ -10,49 +10,37 @@ import { expect, memoryEnv, seat, test } from 'claude-code/testing'
1010
1111seat ( 'builtin' )
1212
13- const SURVEY : CommandRunInput = {
14- command : 'survey' ,
15- args : '' ,
16- origin : { kind : 'composer' } ,
17- }
18- const SHOWN : CommandRunInput = {
19- command : 'shown' ,
20- args : '' ,
21- origin : { kind : 'composer' } ,
22- }
2313const BEARER : SessionAuthorization = { handle : 'the-handle' , kind : 'bearer' }
2414const ACCEPTED : HttpResponse = { status : 200 , ok : true , headers : { } , text : '' }
2515
2616/**
27- * A plugin that records through `$.telemetry`: `/survey` logs an answered
28- * survey, `/shown` a row under the built-in panel's own name; each answers
29- * "sent", or why the row was refused.
17+ * `/record <event>`, which the recording plugin answers.
18+ */
19+ const record = ( event : string ) : CommandRunInput => ( {
20+ command : 'record' ,
21+ args : event ,
22+ origin : { kind : 'composer' } ,
23+ } )
24+
25+ /**
26+ * A plugin whose `/record <event>` logs that event through `$.telemetry`,
27+ * answering "sent", or why the row was refused.
3028 */
3129const recording : Plugin = {
3230 name : 'recording' ,
3331 register ( on ) {
34- on ( 'command.run' , { command : 'survey' } , $ =>
35- $ . telemetry
36- . log ( { event : 'survey_answered' , props : { answer : 2 , seen : true } } )
37- . then (
38- ( ) => ( { text : 'sent' } ) ,
39- ( error : unknown ) => ( { text : String ( error ) } ) ,
40- ) ,
41- )
42- on ( 'command.run' , { command : 'shown' } , $ =>
43- $ . telemetry
44- . log ( { event : 'tengu_repl_diff_panel_shown' , props : { seen : true } } )
45- . then (
46- ( ) => ( { text : 'sent' } ) ,
47- ( error : unknown ) => ( { text : String ( error ) } ) ,
48- ) ,
32+ on ( 'command.run' , { command : 'record' } , ( $ , e ) =>
33+ $ . telemetry . log ( { event : e . args , props : { answer : 2 , seen : true } } ) . then (
34+ ( ) => ( { text : 'sent' } ) ,
35+ ( error : unknown ) => ( { text : String ( error ) } ) ,
36+ ) ,
4937 )
5038 } ,
5139}
5240
5341/**
5442 * A first-party session: its id and model, the credential it holds, and
55- * the ingest accepting each row, which is kept as it was posted .
43+ * the ingest accepting each row, each post kept as it was made .
5644 */
5745function firstPartySession (
5846 on : On ,
@@ -72,13 +60,10 @@ function firstPartySession(
7260}
7361
7462/**
75- * The one row a post to the ingest carries.
63+ * The batch a post to the ingest carries, as it was sent .
7664 */
77- function rowOf ( post : Args < 'http.fetch' > | undefined ) {
78- const batch : { events : { event_data : Readonly < Record < string , unknown > > } [ ] } =
79- JSON . parse ( String ( post ?. init ?. body ) )
80-
81- return batch . events [ 0 ] ?. event_data
65+ function batchOf ( post : Args < 'http.fetch' > ) : unknown {
66+ return JSON . parse ( String ( post . init ?. body ) )
8267}
8368
8469test (
@@ -88,14 +73,25 @@ test(
8873 memoryEnv ( on , { USER_TYPE : 'ant' } )
8974 const posts = firstPartySession ( on )
9075
91- expect ( await $ . command . run ( SURVEY ) ) . toEqual ( { text : 'sent' } )
76+ expect ( await $ . command . run ( record ( 'survey_answered' ) ) ) . toEqual ( {
77+ text : 'sent' ,
78+ } )
9279 expect ( posts ) . toHaveLength ( 1 )
93- expect ( posts [ 0 ] ?. init ) . toMatchObject ( { method : 'POST' , auth : 'the-handle' } )
94- expect ( rowOf ( posts [ 0 ] ) ) . toMatchObject ( {
95- event_name : 'tengu_plugin_survey_answered' ,
96- session_id : 'the-session' ,
97- model : 'the-model' ,
98- user_type : 'ant' ,
80+
81+ const [ post ] = posts
82+
83+ expect ( post . init ) . toMatchObject ( { method : 'POST' , auth : 'the-handle' } )
84+ expect ( batchOf ( post ) ) . toMatchObject ( {
85+ events : [
86+ {
87+ event_data : {
88+ event_name : 'tengu_plugin_survey_answered' ,
89+ session_id : 'the-session' ,
90+ model : 'the-model' ,
91+ user_type : 'ant' ,
92+ } ,
93+ } ,
94+ ] ,
9995 } )
10096 } ,
10197)
@@ -107,12 +103,20 @@ test(
107103 memoryEnv ( on , { } )
108104 const posts = firstPartySession ( on )
109105
110- await $ . command . run ( SHOWN )
111-
112- expect ( rowOf ( posts [ 0 ] ) ) . toMatchObject ( {
113- event_name : 'tengu_repl_diff_panel_shown' ,
114- user_type : 'external' ,
115- } )
106+ await $ . command . run ( record ( 'tengu_repl_diff_panel_shown' ) )
107+
108+ expect ( posts . map ( batchOf ) ) . toMatchObject ( [
109+ {
110+ events : [
111+ {
112+ event_data : {
113+ event_name : 'tengu_repl_diff_panel_shown' ,
114+ user_type : 'external' ,
115+ } ,
116+ } ,
117+ ] ,
118+ } ,
119+ ] )
116120 } ,
117121)
118122
@@ -123,7 +127,9 @@ test(
123127 memoryEnv ( on , { DO_NOT_TRACK : '1' } )
124128 const posts = firstPartySession ( on )
125129
126- expect ( await $ . command . run ( SURVEY ) ) . toEqual ( { text : 'sent' } )
130+ expect ( await $ . command . run ( record ( 'survey_answered' ) ) ) . toEqual ( {
131+ text : 'sent' ,
132+ } )
127133 expect ( posts ) . toEqual ( [ ] )
128134 } ,
129135)
@@ -135,7 +141,7 @@ test(
135141 memoryEnv ( on , { CLAUDE_CODE_USE_BEDROCK : '1' } )
136142 const posts = firstPartySession ( on )
137143
138- await $ . command . run ( SURVEY )
144+ await $ . command . run ( record ( 'survey_answered' ) )
139145
140146 expect ( posts ) . toEqual ( [ ] )
141147 } ,
@@ -147,7 +153,7 @@ test(
147153 async ( $ , on ) => {
148154 memoryEnv ( on , { } )
149155 const posts = firstPartySession ( on , null )
150- const { text } = await $ . command . run ( SURVEY )
156+ const { text } = await $ . command . run ( record ( 'survey_answered' ) )
151157
152158 expect ( text ) . toEndWith (
153159 '$.telemetry.log: this session has no first-party credential to ' +
0 commit comments