@ketd/gemini-cli-sdk 0.3.3 → 0.3.5

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.cjs CHANGED
@@ -77,6 +77,101 @@ var JsonInputMessageType = /* @__PURE__ */ ((JsonInputMessageType2) => {
77
77
  return JsonInputMessageType2;
78
78
  })(JsonInputMessageType || {});
79
79
 
80
+ // src/logger.ts
81
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
82
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
83
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
84
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
85
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
86
+ LogLevel2[LogLevel2["SILENT"] = 4] = "SILENT";
87
+ return LogLevel2;
88
+ })(LogLevel || {});
89
+ var consoleLogger = {
90
+ debug: (message, ...args) => console.log(message, ...args),
91
+ info: (message, ...args) => console.log(message, ...args),
92
+ warn: (message, ...args) => console.warn(message, ...args),
93
+ error: (message, ...args) => console.error(message, ...args)
94
+ };
95
+ var silentLogger = {
96
+ debug: () => {
97
+ },
98
+ info: () => {
99
+ },
100
+ warn: () => {
101
+ },
102
+ error: () => {
103
+ }
104
+ };
105
+ var SDKLogger = class {
106
+ logger;
107
+ level;
108
+ prefix;
109
+ constructor(options = {}) {
110
+ this.logger = options.logger || consoleLogger;
111
+ this.level = options.level ?? 1 /* INFO */;
112
+ this.prefix = options.prefix || "";
113
+ }
114
+ /**
115
+ * Update logger configuration
116
+ */
117
+ configure(options) {
118
+ if (options.logger !== void 0) {
119
+ this.logger = options.logger;
120
+ }
121
+ if (options.level !== void 0) {
122
+ this.level = options.level;
123
+ }
124
+ if (options.prefix !== void 0) {
125
+ this.prefix = options.prefix;
126
+ }
127
+ }
128
+ /**
129
+ * Set log level
130
+ */
131
+ setLevel(level) {
132
+ this.level = level;
133
+ }
134
+ /**
135
+ * Set custom logger implementation
136
+ */
137
+ setLogger(logger) {
138
+ this.logger = logger;
139
+ }
140
+ formatMessage(message) {
141
+ return this.prefix ? `${this.prefix} ${message}` : message;
142
+ }
143
+ debug(message, ...args) {
144
+ if (this.level <= 0 /* DEBUG */) {
145
+ this.logger.debug(this.formatMessage(message), ...args);
146
+ }
147
+ }
148
+ info(message, ...args) {
149
+ if (this.level <= 1 /* INFO */) {
150
+ this.logger.info(this.formatMessage(message), ...args);
151
+ }
152
+ }
153
+ warn(message, ...args) {
154
+ if (this.level <= 2 /* WARN */) {
155
+ this.logger.warn(this.formatMessage(message), ...args);
156
+ }
157
+ }
158
+ error(message, ...args) {
159
+ if (this.level <= 3 /* ERROR */) {
160
+ this.logger.error(this.formatMessage(message), ...args);
161
+ }
162
+ }
163
+ };
164
+ var sdkLogger = new SDKLogger({
165
+ prefix: "[GeminiSDK]",
166
+ level: 1 /* INFO */
167
+ });
168
+ function createLogger(component, options = {}) {
169
+ return new SDKLogger({
170
+ ...options,
171
+ prefix: options.prefix || `[${component}]`
172
+ });
173
+ }
174
+
80
175
  // src/query.ts
81
176
  function buildCliArgs(options, prompt) {
82
177
  const args = [];
@@ -108,7 +203,7 @@ function buildCliArgs(options, prompt) {
108
203
  args.push(prompt);
109
204
  return args;
110
205
  }
111
- function buildEnv(options) {
206
+ function buildEnv(options, logger) {
112
207
  const env = {
113
208
  ...process.env,
114
209
  ...options.env
@@ -119,25 +214,19 @@ function buildEnv(options) {
119
214
  if (useVertexAI) {
120
215
  env.GOOGLE_API_KEY = options.apiKey;
121
216
  env.GOOGLE_GENAI_USE_VERTEXAI = "true";
122
- if (options.debug) {
123
- console.log("[SDK] Vertex AI mode: Setting GOOGLE_API_KEY:", options.apiKey.substring(0, 10) + "...");
124
- }
217
+ logger.debug("Vertex AI mode: Setting GOOGLE_API_KEY:", options.apiKey.substring(0, 10) + "...");
125
218
  } else {
126
219
  env.GEMINI_API_KEY = options.apiKey;
127
- if (options.debug) {
128
- console.log("[SDK] Standard mode: Setting GEMINI_API_KEY:", options.apiKey.substring(0, 10) + "...");
129
- }
220
+ logger.debug("Standard mode: Setting GEMINI_API_KEY:", options.apiKey.substring(0, 10) + "...");
130
221
  }
131
222
  }
132
223
  if (!useVertexAI && env.GOOGLE_API_KEY) {
133
224
  delete env.GOOGLE_API_KEY;
134
- if (options.debug) {
135
- console.log("[SDK] Removed GOOGLE_API_KEY from environment (not using Vertex AI)");
136
- }
225
+ logger.debug("Removed GOOGLE_API_KEY from environment (not using Vertex AI)");
137
226
  }
138
227
  if (options.debug) {
139
228
  env.DEBUG = "1";
140
- console.log("[SDK] Environment variables set:", {
229
+ logger.debug("Environment variables set:", {
141
230
  GEMINI_API_KEY: env.GEMINI_API_KEY ? "***" : void 0,
142
231
  GOOGLE_API_KEY: env.GOOGLE_API_KEY ? "***" : void 0,
143
232
  GOOGLE_GENAI_USE_VERTEXAI: env.GOOGLE_GENAI_USE_VERTEXAI,
@@ -147,6 +236,10 @@ function buildEnv(options) {
147
236
  return env;
148
237
  }
149
238
  async function* query(prompt, options) {
239
+ const logger = createLogger("GeminiSDK", {
240
+ logger: options.logger,
241
+ level: options.debug ? 0 /* DEBUG */ : 1 /* INFO */
242
+ });
150
243
  if (!options.pathToGeminiCLI) {
151
244
  throw new GeminiSDKError("pathToGeminiCLI is required");
152
245
  }
@@ -156,7 +249,7 @@ async function* query(prompt, options) {
156
249
  );
157
250
  }
158
251
  const args = buildCliArgs(options, prompt);
159
- const env = buildEnv(options);
252
+ const env = buildEnv(options, logger);
160
253
  const cwd = options.cwd || process.cwd();
161
254
  const nodeExecutable = options.pathToNode || "node";
162
255
  let geminiProcess;
@@ -172,9 +265,7 @@ async function* query(prompt, options) {
172
265
  const stderrChunks = [];
173
266
  geminiProcess.stderr?.on("data", (data) => {
174
267
  stderrChunks.push(data);
175
- if (options.debug) {
176
- console.error("[Gemini CLI stderr]:", data.toString());
177
- }
268
+ logger.error("stderr:", data.toString());
178
269
  });
179
270
  let timeoutId;
180
271
  if (options.timeout) {
@@ -194,10 +285,8 @@ async function* query(prompt, options) {
194
285
  hasYieldedEvents = true;
195
286
  yield event;
196
287
  } catch (parseError) {
197
- if (options.debug) {
198
- console.error("[Gemini SDK] Failed to parse JSON line:", line);
199
- console.error("[Gemini SDK] Parse error:", parseError);
200
- }
288
+ logger.debug("Failed to parse JSON line:", line);
289
+ logger.debug("Parse error:", parseError);
201
290
  }
202
291
  }
203
292
  } catch (error) {
@@ -400,6 +489,10 @@ var GeminiStreamClient = class extends events.EventEmitter {
400
489
  constructor(options) {
401
490
  super();
402
491
  this.options = options;
492
+ this.logger = createLogger("GeminiStreamClient", {
493
+ logger: options.logger,
494
+ level: options.debug ? 0 /* DEBUG */ : 1 /* INFO */
495
+ });
403
496
  if (!options.pathToGeminiCLI) {
404
497
  throw new GeminiSDKError("pathToGeminiCLI is required");
405
498
  }
@@ -414,6 +507,7 @@ var GeminiStreamClient = class extends events.EventEmitter {
414
507
  initEvent = null;
415
508
  initTimeout = null;
416
509
  tempSettingsPath = null;
510
+ logger;
417
511
  /**
418
512
  * Start the Gemini CLI process
419
513
  */
@@ -457,9 +551,11 @@ var GeminiStreamClient = class extends events.EventEmitter {
457
551
  }
458
552
  if (this.process.stderr) {
459
553
  this.process.stderr.on("data", (chunk) => {
460
- if (this.options.debug) {
461
- console.error("[GeminiStreamClient] stderr:", chunk.toString());
554
+ const message = chunk.toString().trim();
555
+ if (!message || message.includes("Flushing log events")) {
556
+ return;
462
557
  }
558
+ this.logger.error("stderr:", message);
463
559
  });
464
560
  }
465
561
  this.emit("started");
@@ -526,6 +622,34 @@ var GeminiStreamClient = class extends events.EventEmitter {
526
622
  };
527
623
  this.writeMessage(message);
528
624
  }
625
+ /**
626
+ * Resume session from a session file
627
+ *
628
+ * This sends a control message to the CLI to:
629
+ * 1. Load history from the specified session file
630
+ * 2. Update the ChatRecordingService to use the session file
631
+ *
632
+ * Used when a warm pool adapter is assigned to a real session that has history.
633
+ *
634
+ * @param sessionFilePath - Path to the session file to resume from
635
+ */
636
+ async resumeSession(sessionFilePath) {
637
+ if (!this.isReady()) {
638
+ throw new GeminiSDKError("Client not ready. Call start() first.");
639
+ }
640
+ if (!sessionFilePath) {
641
+ throw new GeminiSDKError("sessionFilePath is required");
642
+ }
643
+ const message = {
644
+ type: "control" /* CONTROL */,
645
+ control: {
646
+ subtype: "resume_session",
647
+ sessionFilePath
648
+ },
649
+ session_id: this.options.sessionId
650
+ };
651
+ this.writeMessage(message);
652
+ }
529
653
  /**
530
654
  * Stop the CLI process
531
655
  */
@@ -567,11 +691,9 @@ var GeminiStreamClient = class extends events.EventEmitter {
567
691
  if (this.tempSettingsPath) {
568
692
  try {
569
693
  fs__namespace.unlinkSync(this.tempSettingsPath);
570
- if (this.options.debug) {
571
- console.log("[GeminiStreamClient] Cleaned up temp settings:", this.tempSettingsPath);
572
- }
694
+ this.logger.debug("Cleaned up temp settings:", this.tempSettingsPath);
573
695
  } catch (error) {
574
- console.error("[GeminiStreamClient] Failed to clean up temp settings:", error);
696
+ this.logger.error("Failed to clean up temp settings:", error);
575
697
  }
576
698
  this.tempSettingsPath = null;
577
699
  }
@@ -616,9 +738,7 @@ var GeminiStreamClient = class extends events.EventEmitter {
616
738
  }
617
739
  if (!fs__namespace.existsSync(geminiConfigDir)) {
618
740
  fs__namespace.mkdirSync(geminiConfigDir, { recursive: true });
619
- if (this.options.debug) {
620
- console.log("[GeminiStreamClient] Created config directory:", geminiConfigDir);
621
- }
741
+ this.logger.debug("Created config directory:", geminiConfigDir);
622
742
  }
623
743
  this.tempSettingsPath = path2__namespace.join(geminiConfigDir, "settings.json");
624
744
  const settings = {};
@@ -633,10 +753,8 @@ var GeminiStreamClient = class extends events.EventEmitter {
633
753
  }
634
754
  try {
635
755
  fs__namespace.writeFileSync(this.tempSettingsPath, JSON.stringify(settings, null, 2), "utf-8");
636
- if (this.options.debug) {
637
- console.log("[GeminiStreamClient] Wrote settings to:", this.tempSettingsPath);
638
- console.log("[GeminiStreamClient] Settings content:", JSON.stringify(settings, null, 2));
639
- }
756
+ this.logger.debug("Wrote settings to:", this.tempSettingsPath);
757
+ this.logger.debug("Settings content:", JSON.stringify(settings, null, 2));
640
758
  } catch (error) {
641
759
  throw new GeminiSDKError(`Failed to write settings file: ${error}`);
642
760
  }
@@ -654,9 +772,7 @@ var GeminiStreamClient = class extends events.EventEmitter {
654
772
  ];
655
773
  if (this.options.resumeSessionFilePath) {
656
774
  args.push("--resume-from-file", this.options.resumeSessionFilePath);
657
- if (this.options.debug) {
658
- console.log("[GeminiStreamClient] Resuming from session file:", this.options.resumeSessionFilePath);
659
- }
775
+ this.logger.debug("Resuming from session file:", this.options.resumeSessionFilePath);
660
776
  }
661
777
  if (this.options.model) {
662
778
  args.push("--model", this.options.model);
@@ -679,28 +795,20 @@ var GeminiStreamClient = class extends events.EventEmitter {
679
795
  };
680
796
  if (this.options.apiKey) {
681
797
  const useVertexAI = this.options.env?.GOOGLE_GENAI_USE_VERTEXAI === "true";
682
- if (this.options.debug) {
683
- console.log("[GeminiStreamClient] buildEnv() - API Key prefix:", this.options.apiKey.substring(0, 3));
684
- console.log("[GeminiStreamClient] buildEnv() - GOOGLE_GENAI_USE_VERTEXAI:", this.options.env?.GOOGLE_GENAI_USE_VERTEXAI);
685
- console.log("[GeminiStreamClient] buildEnv() - useVertexAI:", useVertexAI);
686
- }
798
+ this.logger.debug("buildEnv() - API Key prefix:", this.options.apiKey.substring(0, 3));
799
+ this.logger.debug("buildEnv() - GOOGLE_GENAI_USE_VERTEXAI:", this.options.env?.GOOGLE_GENAI_USE_VERTEXAI);
800
+ this.logger.debug("buildEnv() - useVertexAI:", useVertexAI);
687
801
  if (useVertexAI) {
688
802
  env.GOOGLE_API_KEY = this.options.apiKey;
689
- if (this.options.debug) {
690
- console.log("[GeminiStreamClient] buildEnv() - Setting GOOGLE_API_KEY for Vertex AI");
691
- }
803
+ this.logger.debug("buildEnv() - Setting GOOGLE_API_KEY for Vertex AI");
692
804
  } else {
693
805
  env.GEMINI_API_KEY = this.options.apiKey;
694
- if (this.options.debug) {
695
- console.log("[GeminiStreamClient] buildEnv() - Setting GEMINI_API_KEY for AI Studio");
696
- }
806
+ this.logger.debug("buildEnv() - Setting GEMINI_API_KEY for AI Studio");
697
807
  }
698
808
  }
699
- if (this.options.debug) {
700
- console.log("[GeminiStreamClient] buildEnv() - Final env has GOOGLE_API_KEY:", !!env.GOOGLE_API_KEY);
701
- console.log("[GeminiStreamClient] buildEnv() - Final env has GEMINI_API_KEY:", !!env.GEMINI_API_KEY);
702
- console.log("[GeminiStreamClient] buildEnv() - Final env GOOGLE_GENAI_USE_VERTEXAI:", env.GOOGLE_GENAI_USE_VERTEXAI);
703
- }
809
+ this.logger.debug("buildEnv() - Final env has GOOGLE_API_KEY:", !!env.GOOGLE_API_KEY);
810
+ this.logger.debug("buildEnv() - Final env has GEMINI_API_KEY:", !!env.GEMINI_API_KEY);
811
+ this.logger.debug("buildEnv() - Final env GOOGLE_GENAI_USE_VERTEXAI:", env.GOOGLE_GENAI_USE_VERTEXAI);
704
812
  return env;
705
813
  }
706
814
  /**
@@ -711,19 +819,15 @@ var GeminiStreamClient = class extends events.EventEmitter {
711
819
  throw new GeminiSDKError("stdin stream not available");
712
820
  }
713
821
  const json = JSON.stringify(message);
714
- if (this.options.debug) {
715
- console.log("[GeminiStreamClient] Writing message to stdin:", json.substring(0, 100));
716
- }
822
+ this.logger.debug("Writing message to stdin:", json.substring(0, 100));
717
823
  const success = this.stdinStream.write(json + "\n", (error) => {
718
824
  if (error) {
719
- console.error("[GeminiStreamClient] Write error:", error);
720
- } else if (this.options.debug) {
721
- console.log("[GeminiStreamClient] Write callback: message flushed to stdin");
825
+ this.logger.error("Write error:", error);
826
+ } else {
827
+ this.logger.debug("Write callback: message flushed to stdin");
722
828
  }
723
829
  });
724
- if (this.options.debug) {
725
- console.log("[GeminiStreamClient] Write success:", success, "Stream writable:", this.stdinStream.writable);
726
- }
830
+ this.logger.debug("Write success:", success, "Stream writable:", this.stdinStream.writable);
727
831
  }
728
832
  /**
729
833
  * Start reading JSONL events from stdout
@@ -738,23 +842,17 @@ var GeminiStreamClient = class extends events.EventEmitter {
738
842
  return;
739
843
  }
740
844
  if (trimmed.startsWith("[")) {
741
- if (this.options.debug) {
742
- console.log("[GeminiStreamClient] Skipping debug output:", trimmed.substring(0, 100));
743
- }
744
845
  return;
745
846
  }
746
847
  try {
747
848
  const event = JSON.parse(trimmed);
748
849
  this.handleEvent(event);
749
850
  } catch (error) {
750
- console.error("[GeminiStreamClient] Failed to parse JSON:", trimmed);
751
- console.error("[GeminiStreamClient] Error:", error);
851
+ this.logger.error("Failed to parse JSON:", trimmed);
852
+ this.logger.error("Error:", error);
752
853
  }
753
854
  });
754
855
  this.readlineInterface.on("close", () => {
755
- if (this.options.debug) {
756
- console.log("[GeminiStreamClient] readline interface closed");
757
- }
758
856
  });
759
857
  }
760
858
  /**
@@ -796,9 +894,7 @@ var GeminiStreamClient = class extends events.EventEmitter {
796
894
  * Handle process exit
797
895
  */
798
896
  handleProcessExit(code, signal) {
799
- if (this.options.debug) {
800
- console.log("[GeminiStreamClient] Process exited:", { code, signal });
801
- }
897
+ this.logger.debug("Process exited:", { code, signal });
802
898
  if (code !== 0 && code !== null) {
803
899
  this.status = "error" /* ERROR */;
804
900
  this.emit("error", new GeminiSDKError(`Process exited with code ${code}`, code));
@@ -817,7 +913,7 @@ var GeminiStreamClient = class extends events.EventEmitter {
817
913
  * Handle process error
818
914
  */
819
915
  handleProcessError(error) {
820
- console.error("[GeminiStreamClient] Process error:", error);
916
+ this.logger.error("Process error:", error);
821
917
  this.status = "error" /* ERROR */;
822
918
  this.emit("error", error);
823
919
  }
@@ -876,7 +972,7 @@ function validateModel(model) {
876
972
  return defaultModel;
877
973
  }
878
974
  if (!model.startsWith("gemini-")) {
879
- console.warn(`Warning: Model name "${model}" does not start with "gemini-"`);
975
+ sdkLogger.warn(`Warning: Model name "${model}" does not start with "gemini-"`);
880
976
  }
881
977
  return model;
882
978
  }
@@ -901,12 +997,17 @@ exports.GeminiSDKError = GeminiSDKError;
901
997
  exports.GeminiStreamClient = GeminiStreamClient;
902
998
  exports.JsonInputMessageType = JsonInputMessageType;
903
999
  exports.JsonStreamEventType = JsonStreamEventType;
1000
+ exports.LogLevel = LogLevel;
904
1001
  exports.ProcessStatus = ProcessStatus;
1002
+ exports.SDKLogger = SDKLogger;
1003
+ exports.createLogger = createLogger;
905
1004
  exports.findGeminiCLI = findGeminiCLI;
906
1005
  exports.formatDuration = formatDuration;
907
1006
  exports.formatTokens = formatTokens;
908
1007
  exports.getApiKey = getApiKey;
909
1008
  exports.query = query;
1009
+ exports.sdkLogger = sdkLogger;
1010
+ exports.silentLogger = silentLogger;
910
1011
  exports.validateApiKey = validateApiKey;
911
1012
  exports.validateModel = validateModel;
912
1013
  //# sourceMappingURL=index.cjs.map