@@ -64,6 +64,74 @@ public KimiMessage readMessage(String json) {
6464 }
6565 }
6666
67+ public KimiSession readSession (String json ) {
68+ JsonNode root = readObject (json , "Kimi session" );
69+ Map <String , JsonNode > extensions = extensions (root , "sessionId" , "session_id" , "model" , "mode" );
70+ return new KimiSession (firstText (root , "sessionId" , "session_id" ),
71+ root .path ("model" ).asText (null ),
72+ root .path ("mode" ).asText (null ),
73+ extensions );
74+ }
75+
76+ public KimiPromptResult readPromptResult (String json ) {
77+ JsonNode root = readObject (json , "Kimi prompt result" );
78+ JsonNode usageNode = root .path ("usage" );
79+ KimiUsage usage = usageNode .isObject ()
80+ ? new KimiUsage (usageNode .path ("inputTokens" ).asLong (0L ),
81+ usageNode .path ("outputTokens" ).asLong (0L ),
82+ usageNode .path ("totalTokens" ).asLong (0L ))
83+ : null ;
84+ Map <String , JsonNode > extensions = extensions (root ,
85+ "sessionId" , "session_id" , "stopReason" , "stop_reason" , "content" , "usage" );
86+ return new KimiPromptResult (firstText (root , "sessionId" , "session_id" ),
87+ KimiStopReason .of (firstText (root , "stopReason" , "stop_reason" )),
88+ root .path ("content" ).asText (null ),
89+ usage ,
90+ extensions );
91+ }
92+
93+ private JsonNode readObject (String json , String what ) {
94+ if (json == null ) {
95+ throw new NullPointerException ("json" );
96+ }
97+ try {
98+ JsonNode root = mapper .readTree (json );
99+ if (root == null || !root .isObject ()) {
100+ throw new KimiException (what + " must be a JSON object" );
101+ }
102+ return root ;
103+ } catch (KimiException e ) {
104+ throw e ;
105+ } catch (Exception e ) {
106+ throw new KimiException ("Failed to parse " + what , e );
107+ }
108+ }
109+
110+ private Map <String , JsonNode > extensions (JsonNode root , String ... known ) {
111+ Map <String , Boolean > knownNames = new LinkedHashMap <String , Boolean >();
112+ for (String name : known ) {
113+ knownNames .put (name , Boolean .TRUE );
114+ }
115+ Map <String , JsonNode > result = new LinkedHashMap <String , JsonNode >();
116+ for (Map .Entry <String , JsonNode > entry : root .properties ()) {
117+ if (!knownNames .containsKey (entry .getKey ())) {
118+ JsonNode value = entry .getValue ();
119+ result .put (entry .getKey (), value == null ? null : value .deepCopy ());
120+ }
121+ }
122+ return result ;
123+ }
124+
125+ private String firstText (JsonNode node , String ... names ) {
126+ for (String name : names ) {
127+ String value = node .path (name ).asText (null );
128+ if (value != null && !value .isEmpty ()) {
129+ return value ;
130+ }
131+ }
132+ return null ;
133+ }
134+
67135 private KimiContentBlock readContentBlock (JsonNode node ) {
68136 if (node == null || !node .isObject ()) {
69137 return new KimiUnknownContentBlock (null , node == null ? mapper .nullNode () : node );
0 commit comments