agentram 0.1.7 → 0.1.9

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/agentram/cli.py CHANGED
@@ -825,6 +825,8 @@ def model_error_hint(message: str) -> str:
825
825
  return message + " | Fix: start your OpenAI-compatible server at base_url, or change --base-url."
826
826
  if "http 404" in lower or "404: not found" in lower:
827
827
  return message + " | Fix: verify base_url includes /v1, provider supports /chat/completions, and model name exists."
828
+ if "http 400" in lower and "not supported" in lower:
829
+ return message + " | Fix: this account/provider rejects that model. Bind a supported model name from your local endpoint."
828
830
  if "returned non-json" in lower or "expecting value" in lower:
829
831
  return message + " | Fix: endpoint returned empty/HTML/non-JSON. Check base_url, auth key, proxy, and server logs."
830
832
  if "missing api key env" in lower:
@@ -4,6 +4,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
4
4
  from dataclasses import dataclass, field
5
5
  import json
6
6
  import os
7
+ import re
7
8
  import shlex
8
9
  import subprocess
9
10
  import urllib.error
@@ -139,6 +140,9 @@ class MultiModelCodingOrchestrator:
139
140
  try:
140
141
  data = json.loads(raw)
141
142
  except json.JSONDecodeError as error:
143
+ streamed = parse_openai_sse(raw)
144
+ if streamed:
145
+ return streamed
142
146
  raise RuntimeError(f"OpenAI-compatible returned non-JSON at {url} | response={raw[:500]}") from error
143
147
  return str(data.get("choices", [{}])[0].get("message", {}).get("content", ""))
144
148
 
@@ -188,3 +192,38 @@ class MultiModelCodingOrchestrator:
188
192
  if process.returncode != 0:
189
193
  raise RuntimeError(error or f"claude command failed with exit code {process.returncode}")
190
194
  return output or error
195
+
196
+ def parse_openai_sse(raw: str) -> str:
197
+ parts: list[str] = []
198
+ for line in raw.splitlines():
199
+ stripped = line.strip()
200
+ if not stripped.startswith("data:"):
201
+ continue
202
+ payload = stripped[5:].strip()
203
+ if not payload or payload == "[DONE]":
204
+ continue
205
+ try:
206
+ item = json.loads(payload)
207
+ except json.JSONDecodeError:
208
+ continue
209
+ choices = item.get("choices", [])
210
+ if not choices or not isinstance(choices, list):
211
+ continue
212
+ choice = choices[0]
213
+ if not isinstance(choice, dict):
214
+ continue
215
+ delta = choice.get("delta", {})
216
+ if isinstance(delta, dict):
217
+ content = delta.get("content")
218
+ if content:
219
+ parts.append(str(content))
220
+ message = choice.get("message", {})
221
+ if isinstance(message, dict) and message.get("content"):
222
+ parts.append(str(message.get("content")))
223
+ return strip_thinking_blocks("".join(parts)).strip()
224
+
225
+ def strip_thinking_blocks(text: str) -> str:
226
+ text = re.sub(r"<thinking>.*?</thinking>", "", text, flags=re.DOTALL | re.IGNORECASE)
227
+ text = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL | re.IGNORECASE)
228
+ text = re.sub(r"^\s*</?(thinking|think)>\s*", "", text, flags=re.IGNORECASE)
229
+ return text.strip()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentram",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Async, model-agnostic Working RAM for coding agents.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/trancongnghia/AGENT_RAM#readme",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agentram"
7
- version = "0.1.7"
7
+ version = "0.1.9"
8
8
  description = "Async, model-agnostic RAM layer for agentic coding tools."
9
9
  readme = "README.md"
10
10
  license = "MIT"