@ketd/gemini-cli-sdk 0.3.8 → 0.4.0

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.d.cts CHANGED
@@ -545,7 +545,7 @@ interface UserInputMessage {
545
545
  /**
546
546
  * Control subtypes for control messages
547
547
  */
548
- type ControlSubtype = 'interrupt' | 'cancel' | 'shutdown' | 'truncate_history' | 'resume_session' | 'replace_history';
548
+ type ControlSubtype = 'interrupt' | 'cancel' | 'shutdown' | 'truncate_history' | 'resume_session' | 'replace_history' | 'set_model';
549
549
  /**
550
550
  * Interrupt control - stop current processing
551
551
  */
@@ -590,12 +590,21 @@ interface ReplaceHistoryControl {
590
590
  parts: unknown[];
591
591
  }>;
592
592
  }
593
+ /**
594
+ * Set model control - switch model for subsequent responses
595
+ * Note: Gemini CLI binary support is pending; currently the host adapter restarts the process.
596
+ */
597
+ interface SetModelControl {
598
+ subtype: 'set_model';
599
+ /** The model identifier to switch to */
600
+ model: string;
601
+ }
593
602
  /**
594
603
  * Control message sent to CLI
595
604
  */
596
605
  interface ControlInputMessage {
597
606
  type: JsonInputMessageType.CONTROL;
598
- control: InterruptControl | TruncateHistoryControl | ResumeSessionControl | ReplaceHistoryControl;
607
+ control: InterruptControl | TruncateHistoryControl | ResumeSessionControl | ReplaceHistoryControl | SetModelControl;
599
608
  session_id?: string;
600
609
  }
601
610
  /**
@@ -1011,6 +1020,8 @@ declare class GeminiStreamClient extends EventEmitter$1 {
1011
1020
  private initTimeout;
1012
1021
  private tempSettingsPath;
1013
1022
  private logger;
1023
+ /** stderr 行缓冲,处理 chunk 分片导致的半行问题 */
1024
+ private stderrLineBuffer;
1014
1025
  constructor(options: GeminiStreamOptions);
1015
1026
  /**
1016
1027
  * Start the Gemini CLI process
@@ -1069,6 +1080,14 @@ declare class GeminiStreamClient extends EventEmitter$1 {
1069
1080
  role: string;
1070
1081
  parts: unknown[];
1071
1082
  }>): Promise<void>;
1083
+ /**
1084
+ * Switch model for subsequent responses.
1085
+ * Note: Requires Gemini CLI binary support for the 'set_model' control subtype.
1086
+ * Currently a preparatory API — the host adapter uses process restart to switch models.
1087
+ *
1088
+ * @param model - The model identifier to switch to
1089
+ */
1090
+ setModel(model: string): Promise<void>;
1072
1091
  /**
1073
1092
  * Send a response to an ask_user request from the CLI
1074
1093
  *
@@ -1144,6 +1163,20 @@ declare class GeminiStreamClient extends EventEmitter$1 {
1144
1163
  * Handle process error
1145
1164
  */
1146
1165
  private handleProcessError;
1166
+ /**
1167
+ * 处理 stderr chunk:按行切分并识别 turn finished reason
1168
+ */
1169
+ private processStderrChunk;
1170
+ /**
1171
+ * 进程结束时,处理 stderr 缓冲里最后一行(若存在)
1172
+ */
1173
+ private flushStderrLineBuffer;
1174
+ /**
1175
+ * 处理单行 stderr:
1176
+ * - 识别 [StreamJsonMode] Turn finished: <reason>,并发出 FINISHED 结构化事件
1177
+ * - 其余日志按原行为输出
1178
+ */
1179
+ private processStderrLine;
1147
1180
  }
1148
1181
 
1149
1182
  /**
@@ -1199,4 +1232,4 @@ declare function formatDuration(ms: number): string;
1199
1232
  */
1200
1233
  declare function formatTokens(tokens: number): string;
1201
1234
 
1202
- export { type AskUserEvent, type AskUserResponseInputMessage, type ContextConfig, type ControlInputMessage, type ControlSubtype, type ErrorEvent, ExitCode, GeminiClient, type GeminiOptions, GeminiSDKError, GeminiStreamClient, type GeminiStreamOptions, type HooksConfiguration, type InitEvent, type InterruptControl, type JsonInputMessage, JsonInputMessageType, type JsonStreamEvent, JsonStreamEventType, LogLevel, type Logger, type LoggerOptions, type MCPServerConfig, type MCPServersConfig, type MessageEvent, ProcessStatus, type QueryResult, type Question, type QuestionOption, QuestionType, type ResultEvent, type ResumeSessionControl, SDKLogger, type StreamStats, type ThoughtEvent, type ToolPermissionDecision, type ToolPermissionRequest, type ToolResultEvent, type ToolUseEvent, type ToolsConfig, type TruncateHistoryControl, type UserInputMessage, createLogger, findGeminiCLI, formatDuration, formatTokens, getApiKey, query, sdkLogger, silentLogger, validateApiKey, validateModel };
1235
+ export { type AskUserEvent, type AskUserResponseInputMessage, type ContextConfig, type ControlInputMessage, type ControlSubtype, type ErrorEvent, ExitCode, GeminiClient, type GeminiOptions, GeminiSDKError, GeminiStreamClient, type GeminiStreamOptions, type HooksConfiguration, type InitEvent, type InterruptControl, type JsonInputMessage, JsonInputMessageType, type JsonStreamEvent, JsonStreamEventType, LogLevel, type Logger, type LoggerOptions, type MCPServerConfig, type MCPServersConfig, type MessageEvent, ProcessStatus, type QueryResult, type Question, type QuestionOption, QuestionType, type ReplaceHistoryControl, type ResultEvent, type ResumeSessionControl, SDKLogger, type SetModelControl, type StreamStats, type ThoughtEvent, type ToolPermissionDecision, type ToolPermissionRequest, type ToolResultEvent, type ToolUseEvent, type ToolsConfig, type TruncateHistoryControl, type UserInputMessage, createLogger, findGeminiCLI, formatDuration, formatTokens, getApiKey, query, sdkLogger, silentLogger, validateApiKey, validateModel };
package/dist/index.d.ts CHANGED
@@ -545,7 +545,7 @@ interface UserInputMessage {
545
545
  /**
546
546
  * Control subtypes for control messages
547
547
  */
548
- type ControlSubtype = 'interrupt' | 'cancel' | 'shutdown' | 'truncate_history' | 'resume_session' | 'replace_history';
548
+ type ControlSubtype = 'interrupt' | 'cancel' | 'shutdown' | 'truncate_history' | 'resume_session' | 'replace_history' | 'set_model';
549
549
  /**
550
550
  * Interrupt control - stop current processing
551
551
  */
@@ -590,12 +590,21 @@ interface ReplaceHistoryControl {
590
590
  parts: unknown[];
591
591
  }>;
592
592
  }
593
+ /**
594
+ * Set model control - switch model for subsequent responses
595
+ * Note: Gemini CLI binary support is pending; currently the host adapter restarts the process.
596
+ */
597
+ interface SetModelControl {
598
+ subtype: 'set_model';
599
+ /** The model identifier to switch to */
600
+ model: string;
601
+ }
593
602
  /**
594
603
  * Control message sent to CLI
595
604
  */
596
605
  interface ControlInputMessage {
597
606
  type: JsonInputMessageType.CONTROL;
598
- control: InterruptControl | TruncateHistoryControl | ResumeSessionControl | ReplaceHistoryControl;
607
+ control: InterruptControl | TruncateHistoryControl | ResumeSessionControl | ReplaceHistoryControl | SetModelControl;
599
608
  session_id?: string;
600
609
  }
601
610
  /**
@@ -1011,6 +1020,8 @@ declare class GeminiStreamClient extends EventEmitter$1 {
1011
1020
  private initTimeout;
1012
1021
  private tempSettingsPath;
1013
1022
  private logger;
1023
+ /** stderr 行缓冲,处理 chunk 分片导致的半行问题 */
1024
+ private stderrLineBuffer;
1014
1025
  constructor(options: GeminiStreamOptions);
1015
1026
  /**
1016
1027
  * Start the Gemini CLI process
@@ -1069,6 +1080,14 @@ declare class GeminiStreamClient extends EventEmitter$1 {
1069
1080
  role: string;
1070
1081
  parts: unknown[];
1071
1082
  }>): Promise<void>;
1083
+ /**
1084
+ * Switch model for subsequent responses.
1085
+ * Note: Requires Gemini CLI binary support for the 'set_model' control subtype.
1086
+ * Currently a preparatory API — the host adapter uses process restart to switch models.
1087
+ *
1088
+ * @param model - The model identifier to switch to
1089
+ */
1090
+ setModel(model: string): Promise<void>;
1072
1091
  /**
1073
1092
  * Send a response to an ask_user request from the CLI
1074
1093
  *
@@ -1144,6 +1163,20 @@ declare class GeminiStreamClient extends EventEmitter$1 {
1144
1163
  * Handle process error
1145
1164
  */
1146
1165
  private handleProcessError;
1166
+ /**
1167
+ * 处理 stderr chunk:按行切分并识别 turn finished reason
1168
+ */
1169
+ private processStderrChunk;
1170
+ /**
1171
+ * 进程结束时,处理 stderr 缓冲里最后一行(若存在)
1172
+ */
1173
+ private flushStderrLineBuffer;
1174
+ /**
1175
+ * 处理单行 stderr:
1176
+ * - 识别 [StreamJsonMode] Turn finished: <reason>,并发出 FINISHED 结构化事件
1177
+ * - 其余日志按原行为输出
1178
+ */
1179
+ private processStderrLine;
1147
1180
  }
1148
1181
 
1149
1182
  /**
@@ -1199,4 +1232,4 @@ declare function formatDuration(ms: number): string;
1199
1232
  */
1200
1233
  declare function formatTokens(tokens: number): string;
1201
1234
 
1202
- export { type AskUserEvent, type AskUserResponseInputMessage, type ContextConfig, type ControlInputMessage, type ControlSubtype, type ErrorEvent, ExitCode, GeminiClient, type GeminiOptions, GeminiSDKError, GeminiStreamClient, type GeminiStreamOptions, type HooksConfiguration, type InitEvent, type InterruptControl, type JsonInputMessage, JsonInputMessageType, type JsonStreamEvent, JsonStreamEventType, LogLevel, type Logger, type LoggerOptions, type MCPServerConfig, type MCPServersConfig, type MessageEvent, ProcessStatus, type QueryResult, type Question, type QuestionOption, QuestionType, type ResultEvent, type ResumeSessionControl, SDKLogger, type StreamStats, type ThoughtEvent, type ToolPermissionDecision, type ToolPermissionRequest, type ToolResultEvent, type ToolUseEvent, type ToolsConfig, type TruncateHistoryControl, type UserInputMessage, createLogger, findGeminiCLI, formatDuration, formatTokens, getApiKey, query, sdkLogger, silentLogger, validateApiKey, validateModel };
1235
+ export { type AskUserEvent, type AskUserResponseInputMessage, type ContextConfig, type ControlInputMessage, type ControlSubtype, type ErrorEvent, ExitCode, GeminiClient, type GeminiOptions, GeminiSDKError, GeminiStreamClient, type GeminiStreamOptions, type HooksConfiguration, type InitEvent, type InterruptControl, type JsonInputMessage, JsonInputMessageType, type JsonStreamEvent, JsonStreamEventType, LogLevel, type Logger, type LoggerOptions, type MCPServerConfig, type MCPServersConfig, type MessageEvent, ProcessStatus, type QueryResult, type Question, type QuestionOption, QuestionType, type ReplaceHistoryControl, type ResultEvent, type ResumeSessionControl, SDKLogger, type SetModelControl, type StreamStats, type ThoughtEvent, type ToolPermissionDecision, type ToolPermissionRequest, type ToolResultEvent, type ToolUseEvent, type ToolsConfig, type TruncateHistoryControl, type UserInputMessage, createLogger, findGeminiCLI, formatDuration, formatTokens, getApiKey, query, sdkLogger, silentLogger, validateApiKey, validateModel };
package/dist/index.js CHANGED
@@ -492,6 +492,8 @@ var GeminiStreamClient = class extends EventEmitter {
492
492
  initTimeout = null;
493
493
  tempSettingsPath = null;
494
494
  logger;
495
+ /** stderr 行缓冲,处理 chunk 分片导致的半行问题 */
496
+ stderrLineBuffer = "";
495
497
  /**
496
498
  * Start the Gemini CLI process
497
499
  */
@@ -535,11 +537,7 @@ var GeminiStreamClient = class extends EventEmitter {
535
537
  }
536
538
  if (this.process.stderr) {
537
539
  this.process.stderr.on("data", (chunk) => {
538
- const message = chunk.toString().trim();
539
- if (!message || message.includes("Flushing log events")) {
540
- return;
541
- }
542
- this.logger.error("stderr:", message);
540
+ this.processStderrChunk(chunk.toString());
543
541
  });
544
542
  }
545
543
  this.emit("started");
@@ -670,6 +668,30 @@ var GeminiStreamClient = class extends EventEmitter {
670
668
  };
671
669
  this.writeMessage(message);
672
670
  }
671
+ /**
672
+ * Switch model for subsequent responses.
673
+ * Note: Requires Gemini CLI binary support for the 'set_model' control subtype.
674
+ * Currently a preparatory API — the host adapter uses process restart to switch models.
675
+ *
676
+ * @param model - The model identifier to switch to
677
+ */
678
+ async setModel(model) {
679
+ if (!this.isReady()) {
680
+ throw new GeminiSDKError("Client not ready. Call start() first.");
681
+ }
682
+ if (!model || typeof model !== "string") {
683
+ throw new GeminiSDKError("Model must be a non-empty string.");
684
+ }
685
+ const message = {
686
+ type: "control" /* CONTROL */,
687
+ control: {
688
+ subtype: "set_model",
689
+ model
690
+ },
691
+ session_id: this.options.sessionId
692
+ };
693
+ this.writeMessage(message);
694
+ }
673
695
  /**
674
696
  * Send a response to an ask_user request from the CLI
675
697
  *
@@ -952,6 +974,7 @@ var GeminiStreamClient = class extends EventEmitter {
952
974
  * Handle process exit
953
975
  */
954
976
  handleProcessExit(code, signal) {
977
+ this.flushStderrLineBuffer();
955
978
  this.logger.debug("Process exited:", { code, signal });
956
979
  if (code !== 0 && code !== null) {
957
980
  this.status = "error" /* ERROR */;
@@ -975,6 +998,50 @@ var GeminiStreamClient = class extends EventEmitter {
975
998
  this.status = "error" /* ERROR */;
976
999
  this.emit("error", error);
977
1000
  }
1001
+ /**
1002
+ * 处理 stderr chunk:按行切分并识别 turn finished reason
1003
+ */
1004
+ processStderrChunk(chunkText) {
1005
+ this.stderrLineBuffer += chunkText;
1006
+ const lines = this.stderrLineBuffer.split(/\r?\n/);
1007
+ this.stderrLineBuffer = lines.pop() ?? "";
1008
+ for (const line of lines) {
1009
+ this.processStderrLine(line);
1010
+ }
1011
+ }
1012
+ /**
1013
+ * 进程结束时,处理 stderr 缓冲里最后一行(若存在)
1014
+ */
1015
+ flushStderrLineBuffer() {
1016
+ if (!this.stderrLineBuffer) return;
1017
+ this.processStderrLine(this.stderrLineBuffer);
1018
+ this.stderrLineBuffer = "";
1019
+ }
1020
+ /**
1021
+ * 处理单行 stderr:
1022
+ * - 识别 [StreamJsonMode] Turn finished: <reason>,并发出 FINISHED 结构化事件
1023
+ * - 其余日志按原行为输出
1024
+ */
1025
+ processStderrLine(rawLine) {
1026
+ const line = rawLine.trim();
1027
+ if (!line || line.includes("Flushing log events")) {
1028
+ return;
1029
+ }
1030
+ const match = line.match(/\[StreamJsonMode\]\s+Turn finished:\s*(.+)\s*$/);
1031
+ if (match) {
1032
+ const reason = match[1]?.trim();
1033
+ if (reason) {
1034
+ this.emit("event", {
1035
+ type: "finished" /* FINISHED */,
1036
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1037
+ value: {
1038
+ reason
1039
+ }
1040
+ });
1041
+ }
1042
+ }
1043
+ this.logger.error("stderr:", line);
1044
+ }
978
1045
  };
979
1046
  function findGeminiCLI(cwd = process.cwd()) {
980
1047
  if (process.env.GEMINI_CLI_PATH) {