micro-models-agent 0.24.4 → 0.24.6

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.
Files changed (2) hide show
  1. package/dist/main.js +40 -24
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -4435,12 +4435,12 @@ class OpenAICompatProvider {
4435
4435
  };
4436
4436
  this.rateLimiter = createRateLimiter(config.rateLimits);
4437
4437
  }
4438
- async* chat(messages, tools) {
4438
+ async* chat(messages, tools, signal) {
4439
4439
  if (!this.rateLimiter.canMakeRequest()) {
4440
4440
  throw new Error(`Rate limit exceeded: ${this.rateLimiter.getConfig().maxRequestsPerMinute} requests per minute`);
4441
4441
  }
4442
4442
  this.rateLimiter.recordRequest();
4443
- const streamResult = this.doStream(messages, tools);
4443
+ const streamResult = this.doStream(messages, tools, signal);
4444
4444
  let hasToolCall = false;
4445
4445
  let hasText = false;
4446
4446
  let reasoningAcc = "";
@@ -4455,13 +4455,13 @@ class OpenAICompatProvider {
4455
4455
  yield chunk;
4456
4456
  }
4457
4457
  if (!hasToolCall && !hasText) {
4458
- const fallback = await this.doNonStreaming(messages, tools);
4458
+ const fallback = await this.doNonStreaming(messages, tools, signal);
4459
4459
  for (const chunk of fallback) {
4460
4460
  yield chunk;
4461
4461
  }
4462
4462
  }
4463
4463
  }
4464
- async* doStream(messages, tools) {
4464
+ async* doStream(messages, tools, externalSignal) {
4465
4465
  const body = {
4466
4466
  model: this.model,
4467
4467
  messages,
@@ -4488,6 +4488,15 @@ class OpenAICompatProvider {
4488
4488
  const controller = new AbortController;
4489
4489
  const totalTimeoutMs = 120000;
4490
4490
  const timeoutId = setTimeout(() => controller.abort(), totalTimeoutMs);
4491
+ if (externalSignal) {
4492
+ if (externalSignal.aborted) {
4493
+ controller.abort();
4494
+ } else {
4495
+ externalSignal.addEventListener("abort", () => controller.abort(), {
4496
+ once: true
4497
+ });
4498
+ }
4499
+ }
4491
4500
  const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
4492
4501
  method: "POST",
4493
4502
  headers,
@@ -4591,7 +4600,7 @@ class OpenAICompatProvider {
4591
4600
  reader.releaseLock();
4592
4601
  }
4593
4602
  }
4594
- async doNonStreaming(messages, tools) {
4603
+ async doNonStreaming(messages, tools, externalSignal) {
4595
4604
  const body = {
4596
4605
  model: this.model,
4597
4606
  messages,
@@ -4616,11 +4625,15 @@ class OpenAICompatProvider {
4616
4625
  headers["Authorization"] = `Bearer ${this.config.apiKey}`;
4617
4626
  }
4618
4627
  try {
4619
- const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
4628
+ const fetchInit = {
4620
4629
  method: "POST",
4621
4630
  headers,
4622
4631
  body: JSON.stringify(body)
4623
- });
4632
+ };
4633
+ if (externalSignal) {
4634
+ fetchInit.signal = externalSignal;
4635
+ }
4636
+ const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, fetchInit);
4624
4637
  if (!response.ok) {
4625
4638
  const errorText = await response.text();
4626
4639
  throw new Error(t("error.llm_api", {
@@ -9329,7 +9342,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9329
9342
  const textChunks = [];
9330
9343
  this.emitPhase(iteration, "thinking", onPhase);
9331
9344
  try {
9332
- for await (const chunk of llmProvider.chat(history, allTools)) {
9345
+ for await (const chunk of llmProvider.chat(history, allTools, this.abortController?.signal)) {
9333
9346
  if (this.shutdownRequested)
9334
9347
  break;
9335
9348
  if (chunk.type === "text" && chunk.content) {
@@ -26246,9 +26259,8 @@ class Repl {
26246
26259
  this.running = false;
26247
26260
  });
26248
26261
  if (process.stdin.isTTY) {
26249
- readline2.emitKeypressEvents(process.stdin);
26250
- process.stdin.on("keypress", async (str, key) => {
26251
- if (key.name === "escape") {
26262
+ process.stdin.on("data", (chunk) => {
26263
+ if (chunk.length === 1 && chunk[0] === 27) {
26252
26264
  const now = Date.now();
26253
26265
  if (now - this.lastEscTime < this.doubleEscDelay) {
26254
26266
  if (this.agentRunning) {
@@ -26256,25 +26268,15 @@ class Repl {
26256
26268
  ${t("repl.interrupt")}
26257
26269
  `));
26258
26270
  this.agent.shutdown();
26271
+ setTimeout(() => process.exit(1), 3000);
26259
26272
  }
26260
26273
  this.lastEscTime = 0;
26261
26274
  return;
26262
26275
  }
26263
26276
  this.lastEscTime = now;
26264
26277
  }
26265
- if (key.ctrl && key.name === "v" && !this.agentRunning) {
26266
- try {
26267
- const { readClipboardImage: readClipboardImage2, bufferToDataUrl: bufferToDataUrl2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
26268
- const clipBuf = await readClipboardImage2();
26269
- if (clipBuf) {
26270
- const { dataUrl } = await bufferToDataUrl2(clipBuf);
26271
- this.pendingClipboardImage = dataUrl;
26272
- const sizeKb = Math.round(dataUrl.length * 3 / 4 / 1024);
26273
- console.log(pc.green(`
26274
- ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26275
- this.rl.prompt();
26276
- }
26277
- } catch {}
26278
+ if (chunk.length === 1 && chunk[0] === 22 && !this.agentRunning) {
26279
+ this.handlePasteImage();
26278
26280
  }
26279
26281
  });
26280
26282
  }
@@ -26290,6 +26292,20 @@ ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26290
26292
  }
26291
26293
  });
26292
26294
  }
26295
+ async handlePasteImage() {
26296
+ try {
26297
+ const { readClipboardImage: readClipboardImage2, bufferToDataUrl: bufferToDataUrl2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
26298
+ const clipBuf = await readClipboardImage2();
26299
+ if (clipBuf) {
26300
+ const { dataUrl } = await bufferToDataUrl2(clipBuf);
26301
+ this.pendingClipboardImage = dataUrl;
26302
+ const sizeKb = Math.round(dataUrl.length * 3 / 4 / 1024);
26303
+ console.log(pc.green(`
26304
+ ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26305
+ this.rl.prompt();
26306
+ }
26307
+ } catch {}
26308
+ }
26293
26309
  isMultiLineInput(line) {
26294
26310
  if (line.endsWith("\\"))
26295
26311
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micro-models-agent",
3
- "version": "0.24.4",
3
+ "version": "0.24.6",
4
4
  "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
5
  "type": "module",
6
6
  "bin": {