omnius 1.0.210 → 1.0.211

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.js CHANGED
@@ -561829,6 +561829,30 @@ ${blob}
561829
561829
  _buildToolFingerprint(name10, args) {
561830
561830
  return `${name10}:${this._buildExactArgsKey(args)}`;
561831
561831
  }
561832
+ _dedupeToolCallsForResponse(toolCalls, turn) {
561833
+ if (toolCalls.length <= 1)
561834
+ return toolCalls;
561835
+ const seen = /* @__PURE__ */ new Set();
561836
+ const deduped = [];
561837
+ let dropped = 0;
561838
+ for (const tc of toolCalls) {
561839
+ const fp = this._buildToolFingerprint(tc.name, tc.arguments ?? {});
561840
+ if (seen.has(fp)) {
561841
+ dropped++;
561842
+ continue;
561843
+ }
561844
+ seen.add(fp);
561845
+ deduped.push(tc);
561846
+ }
561847
+ if (dropped > 0) {
561848
+ this.emit({
561849
+ type: "status",
561850
+ content: `Response dedupe: dropped ${dropped} exact duplicate tool call(s) before execution (turn ${turn})`,
561851
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
561852
+ });
561853
+ }
561854
+ return deduped;
561855
+ }
561832
561856
  _decodeToolFingerprint(fingerprint) {
561833
561857
  const colonIdx = fingerprint.indexOf(":");
561834
561858
  const toolName = colonIdx > 0 ? fingerprint.slice(0, colonIdx) : fingerprint;
@@ -564689,6 +564713,14 @@ ${memoryLines.join("\n")}`
564689
564713
  if (msg.toolCalls && msg.toolCalls.length > 0) {
564690
564714
  consecutiveTextOnly = 0;
564691
564715
  consecutiveThinkOnly = 0;
564716
+ msg.toolCalls = this._dedupeToolCallsForResponse(msg.toolCalls, turn);
564717
+ if (msg.toolCalls.length === 0) {
564718
+ messages2.push({
564719
+ role: "system",
564720
+ content: "[RESPONSE DEDUPE] All tool calls in the last response were exact duplicates and were dropped. Use the prior results already in context/cache to continue."
564721
+ });
564722
+ continue;
564723
+ }
564692
564724
  const _RESPONSE_CALL_CAPS = {
564693
564725
  small: 2,
564694
564726
  medium: 4,
@@ -567332,6 +567364,14 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
567332
567364
  if (msg.toolCalls && msg.toolCalls.length > 0) {
567333
567365
  consecutiveTextOnly = 0;
567334
567366
  consecutiveThinkOnly = 0;
567367
+ msg.toolCalls = this._dedupeToolCallsForResponse(msg.toolCalls, turn);
567368
+ if (msg.toolCalls.length === 0) {
567369
+ messages2.push({
567370
+ role: "system",
567371
+ content: "[RESPONSE DEDUPE] All tool calls in the last response were exact duplicates and were dropped. Use the prior results already in context/cache to continue."
567372
+ });
567373
+ continue;
567374
+ }
567335
567375
  messages2.push({
567336
567376
  role: "assistant",
567337
567377
  content: msg.content || null,
@@ -572272,6 +572312,54 @@ ${description}`
572272
572312
  releasePoolSlot(poolSuccess);
572273
572313
  }
572274
572314
  }
572315
+ async nativeOllamaChatCompletion(request) {
572316
+ const cleanedMessages = applyMemoryPrefixToMessages(normalizeMessagesForStrictOpenAI(sanitizeHistoryThink(request.messages)), request.memoryPrefix);
572317
+ const requestMessages = injectNoThinkDirective(cleanedMessages);
572318
+ const responseFormat = request.responseFormat ?? request.response_format;
572319
+ const options2 = {
572320
+ temperature: request.temperature,
572321
+ num_predict: request.maxTokens
572322
+ };
572323
+ const reqNumCtx = request.numCtx ?? request.num_ctx;
572324
+ if (Number.isFinite(reqNumCtx) && (reqNumCtx ?? 0) > 0) {
572325
+ options2["num_ctx"] = reqNumCtx;
572326
+ }
572327
+ const body = {
572328
+ model: this.model,
572329
+ messages: requestMessages,
572330
+ stream: false,
572331
+ think: false,
572332
+ options: options2
572333
+ };
572334
+ if (responseFormat !== void 0) {
572335
+ body["format"] = "json";
572336
+ }
572337
+ const effectiveTimeoutMs = Number.isFinite(request.timeoutMs) && request.timeoutMs > 0 ? request.timeoutMs : 0;
572338
+ const timeoutSignal = effectiveTimeoutMs > 0 && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(effectiveTimeoutMs) : void 0;
572339
+ const fetchOpts = {
572340
+ method: "POST",
572341
+ headers: this.authHeaders(),
572342
+ body: JSON.stringify(body)
572343
+ };
572344
+ if (timeoutSignal)
572345
+ fetchOpts.signal = timeoutSignal;
572346
+ const resp = await fetch(`${this.baseUrl}/api/chat`, fetchOpts);
572347
+ if (!resp.ok) {
572348
+ const text = await resp.text().catch(() => "");
572349
+ throw new Error(`Ollama native HTTP ${resp.status}: ${backendHttpErrorDetail(text)}`);
572350
+ }
572351
+ const data = await resp.json();
572352
+ const message2 = data["message"] ?? {};
572353
+ const content = typeof message2["content"] === "string" ? message2["content"] : "";
572354
+ return {
572355
+ choices: [{ message: { content: content || null } }],
572356
+ usage: buildAgenticUsage({
572357
+ totalTokens: numberFromUnknown2(data["prompt_eval_count"]) ?? 0,
572358
+ promptEvalCount: numberFromUnknown2(data["prompt_eval_count"]),
572359
+ completionTokens: numberFromUnknown2(data["eval_count"])
572360
+ })
572361
+ };
572362
+ }
572275
572363
  /** Anthropic Messages API translation — converts our standard format to/from Anthropic's. */
572276
572364
  async _anthropicChatCompletion(request) {
572277
572365
  const systemMsgs = request.messages.filter((m2) => m2.role === "system");
@@ -647266,8 +647354,13 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`,
647266
647354
  const suppressed = telegramThinkSuppressedRequest(request);
647267
647355
  const requestTimeoutMs = Number.isFinite(suppressed.timeoutMs) && (suppressed.timeoutMs ?? 0) > 0 ? suppressed.timeoutMs : void 0;
647268
647356
  const jsonStartMs = Date.now();
647357
+ const nativeOllamaRouter = diagnostics?.backendType === "ollama" && typeof backend.nativeOllamaChatCompletion === "function";
647269
647358
  try {
647270
- jsonModeResult = await this.telegramObservableInference(
647359
+ jsonModeResult = nativeOllamaRouter ? await backend.nativeOllamaChatCompletion({
647360
+ ...suppressed,
647361
+ responseFormat: TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT,
647362
+ disableEmptyContentRecovery: true
647363
+ }) : await this.telegramObservableInference(
647271
647364
  backend,
647272
647365
  {
647273
647366
  ...suppressed,
@@ -647327,7 +647420,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`,
647327
647420
  }
647328
647421
  const plainStartMs = Date.now();
647329
647422
  try {
647330
- const plainResult = await this.telegramObservableInference(
647423
+ const plainResult = nativeOllamaRouter ? await backend.nativeOllamaChatCompletion(suppressed) : await this.telegramObservableInference(
647331
647424
  backend,
647332
647425
  suppressed,
647333
647426
  inferenceKind,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.210",
3
+ "version": "1.0.211",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.210",
9
+ "version": "1.0.211",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -2310,9 +2310,9 @@
2310
2310
  }
2311
2311
  },
2312
2312
  "node_modules/bare-path": {
2313
- "version": "3.0.0",
2314
- "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
2315
- "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
2313
+ "version": "3.0.1",
2314
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.1.tgz",
2315
+ "integrity": "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==",
2316
2316
  "license": "Apache-2.0",
2317
2317
  "optional": true,
2318
2318
  "dependencies": {
@@ -6886,9 +6886,9 @@
6886
6886
  }
6887
6887
  },
6888
6888
  "node_modules/undici": {
6889
- "version": "7.26.0",
6890
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.26.0.tgz",
6891
- "integrity": "sha512-3O9Tf67pGhgOv9jM35AbhkXAKi13f3oy3aE4CSgr+TckGeY+/iu97ZXN+J7DpHPzLbVApFd1IFhcnBjREYXYcg==",
6889
+ "version": "7.27.0",
6890
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.0.tgz",
6891
+ "integrity": "sha512-+t2Z/GwkZQDtu00813aP66ygViGtPHKhhoFZpQKpKrE+9jIgES+Zw+mFNaDWOVRKiuJjuqKHzD3B1sfGg8+ZOQ==",
6892
6892
  "license": "MIT",
6893
6893
  "engines": {
6894
6894
  "node": ">=20.18.1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.210",
3
+ "version": "1.0.211",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",