Ship beta34 with external agent tasks, terminal SSE and live token limits
This commit is contained in:
1 parent
2cca6a66a6
commit
ab7a721fbc
13 files changed
+91
-18
No files matched your search
@@ -33,7 +33,7 @@ jobs:
|
|||||||
- name: Codex bridge regression tests
|
- name: Codex bridge regression tests
|
||||||
run: '"$RUNNER_TEMP/ci-venv/bin/python" -m unittest discover -s apps/desktop/assets/codex-bridge'
|
run: '"$RUNNER_TEMP/ci-venv/bin/python" -m unittest discover -s apps/desktop/assets/codex-bridge'
|
||||||
- name: Native watch and speech mux pytest regressions
|
- name: Native watch and speech mux pytest regressions
|
||||||
run: '"$RUNNER_TEMP/ci-venv/bin/python" -m pytest apps/desktop/assets/codex-bridge/test_bekci_watch.py apps/desktop/assets/codex-bridge/test_native_speech_mux.py -q -p no:cacheprovider -rf'
|
run: '"$RUNNER_TEMP/ci-venv/bin/python" -m pytest apps/desktop/assets/codex-bridge/test_bekci_watch.py apps/desktop/assets/codex-bridge/test_native_speech_mux.py apps/desktop/assets/codex-bridge/test_live_limits.py -q -p no:cacheprovider -rf'
|
||||||
- name: Mobile and desktop startup regression tests
|
- name: Mobile and desktop startup regression tests
|
||||||
run: |
|
run: |
|
||||||
npm install --prefix "$RUNNER_TEMP/mobile-tests" --no-save --ignore-scripts --no-audit --no-fund --legacy-peer-deps vitest@4.1.10 ws@8.21.1
|
npm install --prefix "$RUNNER_TEMP/mobile-tests" --no-save --ignore-scripts --no-audit --no-fund --legacy-peer-deps vitest@4.1.10 ws@8.21.1
|
||||||
|
|||||||
+5
-2
@@ -25,6 +25,8 @@ ayrıntı seviyesi, korunacak mesajlaşmalar, yüzde/token bütçesi ve otomatik
|
|||||||
seçimini sunar. Varsayılanlar: Gemini 3.8 Flash High, yedek Gemini 3 Flash,
|
seçimini sunar. Varsayılanlar: Gemini 3.8 Flash High, yedek Gemini 3 Flash,
|
||||||
10 mesajlaşma, geçişte %70, otomatik tetiklemede %70 ve sonrasında %50.
|
10 mesajlaşma, geçişte %70, otomatik tetiklemede %70 ve sonrasında %50.
|
||||||
Kapasite bağlantıdan gelen model bilgisiyle hesaplanır; 272K genel tavan yoktur.
|
Kapasite bağlantıdan gelen model bilgisiyle hesaplanır; 272K genel tavan yoktur.
|
||||||
|
`/models` içindeki doğrulanmış sayısal bağlam bilgisi, model adından çıkarılan
|
||||||
|
yerel varsayılandan önce gelir; gözlenmiş daha düşük bir gerçek sınır korunur.
|
||||||
Girdi hesabı talimatlar ve araçları da içeren temkinli bir token tahminidir.
|
Girdi hesabı talimatlar ve araçları da içeren temkinli bir token tahminidir.
|
||||||
|
|
||||||
Abonelik modellerinin kendi aralarındaki istekler ve GPT-Live ses yolu özgün
|
Abonelik modellerinin kendi aralarındaki istekler ve GPT-Live ses yolu özgün
|
||||||
@@ -58,8 +60,9 @@ npm run builder --workspace=apps/desktop -- --win nsis --x64 --publish never
|
|||||||
|
|
||||||
Dağıtılacak derleme temiz, yayımlanmış Git commit'inden üretilmelidir. İlk açılış
|
Dağıtılacak derleme temiz, yayımlanmış Git commit'inden üretilmelidir. İlk açılış
|
||||||
ajan kurulumunu paketteki `install-stamp.json` commit'ine sabitler. Windows
|
ajan kurulumunu paketteki `install-stamp.json` commit'ine sabitler. Windows
|
||||||
imzası ve temiz kurulum doğrulanmadan bir paket doğrulanmış üretim sürümü diye
|
paketleri imzasız EXE/ZIP olarak yayımlanır; SHA-256 ve gerçek Windows çalıştırma
|
||||||
sunulmamalıdır. macOS ve Linux paketleri bu beta kapsamında doğrulanmamıştır.
|
kontrolü gereklidir. Kullanıcı açıkça istemeden imzalama yapılmaz. macOS ve Linux
|
||||||
|
paketleri bu beta kapsamında doğrulanmamıştır.
|
||||||
|
|
||||||
## Lisans ve kaynak
|
## Lisans ve kaynak
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import urllib.request
|
|||||||
import gecis_context
|
import gecis_context
|
||||||
|
|
||||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
SURUM = "14" # AITURK IDE'nin bekledigi kopru surumu (codex-link-config.ts CODEX_BRIDGE_VERSION)
|
SURUM = "15" # AITURK IDE'nin bekledigi kopru surumu (codex-link-config.ts CODEX_BRIDGE_VERSION)
|
||||||
try:
|
try:
|
||||||
with open(os.path.abspath(__file__), "rb") as _f:
|
with open(os.path.abspath(__file__), "rb") as _f:
|
||||||
KOD = hashlib.sha256(_f.read()).hexdigest()[:8]
|
KOD = hashlib.sha256(_f.read()).hexdigest()[:8]
|
||||||
|
|||||||
@@ -104,6 +104,18 @@ def portable_reasoning(req):
|
|||||||
return out
|
return out
|
||||||
result = []
|
result = []
|
||||||
for item in items:
|
for item in items:
|
||||||
|
if isinstance(item, dict) and item.get("type") == "agent_message":
|
||||||
|
# Peer messages carry delegated tasks/results. External Responses
|
||||||
|
# translators do not understand this Codex-specific item type.
|
||||||
|
# Keep provenance as data, never as system/developer authority.
|
||||||
|
content = item.get("content") or []
|
||||||
|
if isinstance(content, str):
|
||||||
|
content = [{"type": "input_text", "text": content}]
|
||||||
|
result.append({"type": "message", "role": "user", "content": [
|
||||||
|
{"type": "input_text", "text": "Agent message: " + encoded({
|
||||||
|
"author": item.get("author"), "recipient": item.get("recipient")})}
|
||||||
|
] + content})
|
||||||
|
continue
|
||||||
if not isinstance(item, dict) or item.get("type") != "reasoning":
|
if not isinstance(item, dict) or item.get("type") != "reasoning":
|
||||||
result.append(item)
|
result.append(item)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -348,11 +348,13 @@ def yukle(ua="AstraBridge/1.0 (codex)", timeout=30, home=None, ag=True):
|
|||||||
if not girdiler:
|
if not girdiler:
|
||||||
raise ValueError("Gecitte kullanilabilir OmniRoute sohbet modeli yok")
|
raise ValueError("Gecitte kullanilabilir OmniRoute sohbet modeli yok")
|
||||||
kayitlar = {m["id"]: m for m in metadata if m.get("id")}
|
kayitlar = {m["id"]: m for m in metadata if m.get("id")}
|
||||||
|
ilanlar = {m["id"]: m for m in data if m.get("id")}
|
||||||
nano = pencere.nano_yukle(home, ua, ag=ag) # ag=False: acilista yalniz onbellek
|
nano = pencere.nano_yukle(home, ua, ag=ag) # ag=False: acilista yalniz onbellek
|
||||||
ogr = pencere.ogrenilen(home)
|
ogr = pencere.ogrenilen(home)
|
||||||
aracsiz = pencere.aracsizlar(home)
|
aracsiz = pencere.aracsizlar(home)
|
||||||
for g in girdiler:
|
for g in girdiler:
|
||||||
bilgi = pencere.coz(g["id"], g["kind"], g.get("yol"), kayitlar.get(g["id"]), nano, ogr, aracsiz)
|
bilgi = pencere.coz(g["id"], g["kind"], g.get("yol"), kayitlar.get(g["id"]), nano, ogr, aracsiz,
|
||||||
|
ilan=ilanlar.get(g["id"]))
|
||||||
g["pencere"], g["gorsel"], g["arac"], g["pencere_kaynak"] = (bilgi["pencere"], bilgi["gorsel"],
|
g["pencere"], g["gorsel"], g["arac"], g["pencere_kaynak"] = (bilgi["pencere"], bilgi["gorsel"],
|
||||||
bilgi["arac"], bilgi["kaynak"])
|
bilgi["arac"], bilgi["kaynak"])
|
||||||
g["claude"] = pencere.claude_var(g["kind"], g.get("yol"), kayitlar.get(g["id"]))
|
g["claude"] = pencere.claude_var(g["kind"], g.get("yol"), kayitlar.get(g["id"]))
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ from bekci_watch import MetadataFilter
|
|||||||
# Installed only by owned native launcher, never an HTTP control endpoint.
|
# Installed only by owned native launcher, never an HTTP control endpoint.
|
||||||
WATCH_OWNER = None
|
WATCH_OWNER = None
|
||||||
|
|
||||||
SURUM = "14"
|
SURUM = "15"
|
||||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
try:
|
try:
|
||||||
with open(os.path.abspath(__file__), "rb") as _f:
|
with open(os.path.abspath(__file__), "rb") as _f:
|
||||||
@@ -365,6 +365,10 @@ def arac_semalarini_duzelt(req):
|
|||||||
|
|
||||||
def flatten_request(req, tool_names=None):
|
def flatten_request(req, tool_names=None):
|
||||||
"""additional_tools/namespace/custom -> duz function tools. Donus: custom arac adlari kumesi."""
|
"""additional_tools/namespace/custom -> duz function tools. Donus: custom arac adlari kumesi."""
|
||||||
|
if isinstance(req.get("input"), list) and any(
|
||||||
|
isinstance(item, dict) and item.get("type") == "agent_message" for item in req["input"]):
|
||||||
|
import gecis_context
|
||||||
|
req["input"] = gecis_context.portable_reasoning(req)["input"]
|
||||||
custom = set()
|
custom = set()
|
||||||
tools = []
|
tools = []
|
||||||
tool_names = tool_names if tool_names is not None else {}
|
tool_names = tool_names if tool_names is not None else {}
|
||||||
@@ -1031,11 +1035,11 @@ class H(http.server.BaseHTTPRequestHandler):
|
|||||||
if jev_denetim.muaf_mi(hedef):
|
if jev_denetim.muaf_mi(hedef):
|
||||||
return self._stream(resp, resp.status, tag, rewriter, izle, basliksiz=True)
|
return self._stream(resp, resp.status, tag, rewriter, izle, basliksiz=True)
|
||||||
if gecmedi:
|
if gecmedi:
|
||||||
# Son katman ne dondurduyse o gider, hicbir sey eklenmez; dondurmediyse hicbir sey gitmez.
|
# Headers already declare SSE. A raw upstream JSON/HTML body
|
||||||
if son_govde:
|
# here leaves Codex waiting for a terminal event and retrying.
|
||||||
w(son_govde)
|
event = {"type": "response.failed", "response": {
|
||||||
else:
|
"id": "resp_astrabridge_%d" % time.time_ns(),
|
||||||
event = {"type": "response.failed", "response": {"status": "failed", "error": {
|
"object": "response", "status": "failed", "output": [], "error": {
|
||||||
"code": "jev_no_fallback", "message": "Jev denetiminden gecen cevap alinamadi; gecis kurallarini kontrol edin."}}}
|
"code": "jev_no_fallback", "message": "Jev denetiminden gecen cevap alinamadi; gecis kurallarini kontrol edin."}}}
|
||||||
w(b"event: response.failed\ndata: " + json.dumps(event).encode() + b"\n\n")
|
w(b"event: response.failed\ndata: " + json.dumps(event).encode() + b"\n\n")
|
||||||
else:
|
else:
|
||||||
@@ -1747,7 +1751,7 @@ class H(http.server.BaseHTTPRequestHandler):
|
|||||||
yanit = urllib.request.urlopen(urllib.request.Request(
|
yanit = urllib.request.urlopen(urllib.request.Request(
|
||||||
jev_rota["url"], data=json.dumps(katman_req, ensure_ascii=False).encode("utf-8"), headers=jev_hdrs, method="POST"),
|
jev_rota["url"], data=json.dumps(katman_req, ensure_ascii=False).encode("utf-8"), headers=jev_hdrs, method="POST"),
|
||||||
timeout=UPSTREAM_IDLE_TIMEOUT)
|
timeout=UPSTREAM_IDLE_TIMEOUT)
|
||||||
return (yanit, SseRewriter(custom, hedef=ad, tasma=self._tasma_ogren, aracsiz=self._aracsiz_ogren),
|
return (yanit, SseRewriter(custom, hedef=ad, tasma=self._tasma_ogren, aracsiz=self._aracsiz_ogren, tool_names=tool_names),
|
||||||
f"[{n} {slug}=>{ad}]")
|
f"[{n} {slug}=>{ad}]")
|
||||||
# A 9Router combo (Fusion-*, no provider prefix) runs a whole panel upstream. Once it may
|
# A 9Router combo (Fusion-*, no provider prefix) runs a whole panel upstream. Once it may
|
||||||
# have started (timeout, 504, cut stream) resending it runs and bills it twice (28 Sep 2026);
|
# have started (timeout, 504, cut stream) resending it runs and bills it twice (28 Sep 2026);
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ def _yapraklar(dugum, derinlik=0):
|
|||||||
return cikti
|
return cikti
|
||||||
|
|
||||||
|
|
||||||
def coz(kimlik, tur, yol, kayit=None, nano=None, ogr=None, aracsiz=()):
|
def coz(kimlik, tur, yol, kayit=None, nano=None, ogr=None, aracsiz=(), ilan=None):
|
||||||
"""Bir katalog girdisinin ilan edilecek penceresi ve yetenekleri.
|
"""Bir katalog girdisinin ilan edilecek penceresi ve yetenekleri.
|
||||||
kimlik: gecit kimligi; tur: "combo" | "model"; yol: gecidin aciklamasindaki "saglayici/model" yolu;
|
kimlik: gecit kimligi; tur: "combo" | "model"; yol: gecidin aciklamasindaki "saglayici/model" yolu;
|
||||||
kayit: /router/catalog girdisi (combo topolojisi icin). Donus: {"pencere","gorsel","arac","kaynak"}."""
|
kayit: /router/catalog girdisi (combo topolojisi icin). Donus: {"pencere","gorsel","arac","kaynak"}."""
|
||||||
@@ -246,6 +246,13 @@ def coz(kimlik, tur, yol, kayit=None, nano=None, ogr=None, aracsiz=()):
|
|||||||
m = re.match(r"no-think-(?:9router-)?([a-z0-9]+)-", kimlik or "")
|
m = re.match(r"no-think-(?:9router-)?([a-z0-9]+)-", kimlik or "")
|
||||||
yol = (m.group(1) + "/" + yol[len("no-think/"):]) if m else yol
|
yol = (m.group(1) + "/" + yol[len("no-think/"):]) if m else yol
|
||||||
sonuc = yol_bilgisi(yol, nano) or dict(bilinmeyen)
|
sonuc = yol_bilgisi(yol, nano) or dict(bilinmeyen)
|
||||||
|
# Exact /models metadata is stronger evidence than name-based local
|
||||||
|
# fallbacks. Do not infer a combo's capacity from its display name.
|
||||||
|
ilan = ilan if isinstance(ilan, dict) else {}
|
||||||
|
canli_sinirlar = [ilan[k] for k in ("context_length", "max_input_tokens")
|
||||||
|
if type(ilan.get(k)) is int and TABAN <= ilan[k] <= 10_000_000]
|
||||||
|
if canli_sinirlar:
|
||||||
|
sonuc = {**sonuc, "pencere": min(canli_sinirlar), "kaynak": "saglayici-katalogu"}
|
||||||
if kimlik in aracsiz:
|
if kimlik in aracsiz:
|
||||||
sonuc = {**sonuc, "arac": False}
|
sonuc = {**sonuc, "arac": False}
|
||||||
sinir = (ogr or {}).get(kimlik)
|
sinir = (ogr or {}).get(kimlik)
|
||||||
|
|||||||
@@ -22,6 +22,26 @@ from test_model_switch import env
|
|||||||
|
|
||||||
|
|
||||||
class History(unittest.TestCase):
|
class History(unittest.TestCase):
|
||||||
|
def test_agent_task_survives_external_projection_and_recent_history(self):
|
||||||
|
task = {"type": "agent_message", "id": "amsg_task", "author": "/root",
|
||||||
|
"recipient": "/root/child", "content": [
|
||||||
|
{"type": "input_text", "text": "Message Type: NEW_TASK\nRun CHILD_TOOL_410962"}]}
|
||||||
|
req = {"input": [{"role": "user", "content": "Old setup"}, task]}
|
||||||
|
before = copy.deepcopy(req)
|
||||||
|
self.assertEqual(gc.normalize(req), before)
|
||||||
|
projected = gc.portable_reasoning(req)
|
||||||
|
message = projected["input"][-1]
|
||||||
|
self.assertEqual(message["role"], "user")
|
||||||
|
self.assertEqual(message["content"][1:], task["content"])
|
||||||
|
self.assertIn('/root/child', message["content"][0]["text"])
|
||||||
|
self.assertNotIn("id", message)
|
||||||
|
self.assertEqual(gc.split_history(projected["input"], keep_users=1)[2], [message])
|
||||||
|
self.assertEqual(req, before)
|
||||||
|
self.assertEqual(gc.portable_reasoning(projected), projected)
|
||||||
|
direct = copy.deepcopy(req)
|
||||||
|
env["flatten_request"](direct)
|
||||||
|
self.assertEqual(direct["input"][-1], message)
|
||||||
|
|
||||||
def test_native_function_results_are_not_foreign_or_renamed(self):
|
def test_native_function_results_are_not_foreign_or_renamed(self):
|
||||||
req = {"input": [{"type": "function_call_output", "id": "fco_native",
|
req = {"input": [{"type": "function_call_output", "id": "fco_native",
|
||||||
"call_id": "call_native", "output": "kept"}]}
|
"call_id": "call_native", "output": "kept"}]}
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ class Akis(unittest.TestCase):
|
|||||||
self.assertNotIn(b"yapamam", self.h.wfile.getvalue())
|
self.assertNotIn(b"yapamam", self.h.wfile.getvalue())
|
||||||
self.assertIn(b'response.failed', self.sent())
|
self.assertIn(b'response.failed', self.sent())
|
||||||
|
|
||||||
def test_the_last_layers_own_error_body_is_delivered_untouched(self):
|
def test_last_layer_http_error_terminates_sse_without_leaking_raw_body(self):
|
||||||
class Hata(Exception):
|
class Hata(Exception):
|
||||||
def read(self):
|
def read(self):
|
||||||
return b'{"error": {"message": "katman 4 hatasi"}}'
|
return b'{"error": {"message": "katman 4 hatasi"}}'
|
||||||
@@ -344,7 +344,14 @@ class Akis(unittest.TestCase):
|
|||||||
def ac(ad):
|
def ac(ad):
|
||||||
raise Hata("HTTP 400")
|
raise Hata("HTTP 400")
|
||||||
self.h._denetimli_akis(Yanit(sse("Bunu yapamam.")), "[1]", None, None, "yap", ["Katman-4"], ac)
|
self.h._denetimli_akis(Yanit(sse("Bunu yapamam.")), "[1]", None, None, "yap", ["Katman-4"], ac)
|
||||||
self.assertEqual(self.sent(), b'{"error": {"message": "katman 4 hatasi"}}')
|
raw = self.sent()
|
||||||
|
self.assertTrue(raw.startswith(b"event: response.failed\ndata: "))
|
||||||
|
event = json.loads(raw.split(b"data: ", 1)[1])
|
||||||
|
self.assertEqual(event["response"]["status"], "failed")
|
||||||
|
self.assertEqual(event["response"]["error"]["code"], "jev_no_fallback")
|
||||||
|
self.assertEqual(event["response"]["output"], [])
|
||||||
|
self.assertNotIn(b"katman 4 hatasi", raw)
|
||||||
|
self.assertNotIn(b"Bunu yapamam", raw)
|
||||||
|
|
||||||
def test_unreachable_jev_keeps_the_answer(self):
|
def test_unreachable_jev_keeps_the_answer(self):
|
||||||
self.puanlar = [None]
|
self.puanlar = [None]
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import pencere
|
||||||
|
|
||||||
|
|
||||||
|
def test_exact_combo_limits_override_unknown_and_local_defaults():
|
||||||
|
row = {"context_length": 872000, "max_input_tokens": 872000, "max_output_tokens": 128000}
|
||||||
|
result = pencere.coz("GPT-6-Astra", "combo", None, ilan=row)
|
||||||
|
assert result["pencere"] == 872000
|
||||||
|
assert result["kaynak"] == "saglayici-katalogu"
|
||||||
|
result = pencere.coz("codex-gpt-6-astra", "model", "codex/gpt-6-astra", ilan=row)
|
||||||
|
assert result["pencere"] == 872000
|
||||||
|
|
||||||
|
|
||||||
|
def test_learned_actual_limit_still_wins_and_invalid_metadata_is_ignored():
|
||||||
|
result = pencere.coz("combo", "combo", None, ilan={"context_length": 872000}, ogr={"combo": 500000})
|
||||||
|
assert result["pencere"] == 500000 and result["kaynak"] == "ogrenilen"
|
||||||
|
for value in (True, -1, "872000", 999999999):
|
||||||
|
result = pencere.coz("combo", "combo", None, ilan={"context_length": value})
|
||||||
|
assert result["pencere"] == pencere.VARSAYILAN
|
||||||
@@ -27,7 +27,7 @@ export const CODEX_LINK_REFRESH_URL = `${CODEX_LINK_ORIGIN}/aiturk/codex-baglama
|
|||||||
export const CODEX_LINK_MARKER = '# AITURK IDE Codex Baglama'
|
export const CODEX_LINK_MARKER = '# AITURK IDE Codex Baglama'
|
||||||
// Must equal SURUM in assets/codex-bridge/bridge.py; a running bridge that reports
|
// Must equal SURUM in assets/codex-bridge/bridge.py; a running bridge that reports
|
||||||
// another version is restarted so an updated IDE never keeps an old bridge alive.
|
// another version is restarted so an updated IDE never keeps an old bridge alive.
|
||||||
export const CODEX_BRIDGE_VERSION = '14'
|
export const CODEX_BRIDGE_VERSION = '15'
|
||||||
export const CODEX_LINK_LINE = `openai_base_url = "${CODEX_LINK_ORIGIN}/backend-api/codex" ${CODEX_LINK_MARKER}`
|
export const CODEX_LINK_LINE = `openai_base_url = "${CODEX_LINK_ORIGIN}/backend-api/codex" ${CODEX_LINK_MARKER}`
|
||||||
|
|
||||||
export const CODEX_LINK_RUN_KEY = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run'
|
export const CODEX_LINK_RUN_KEY = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "aiturk-ide",
|
"name": "aiturk-ide",
|
||||||
"productName": "AITURK IDE",
|
"productName": "AITURK IDE",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0-beta.33",
|
"version": "1.0.0-beta.34",
|
||||||
"description": "TurkServis resmi yapay zekâ geliştirme ortamı. Hermes Agent tabanlıdır.",
|
"description": "TurkServis resmi yapay zekâ geliştirme ortamı. Hermes Agent tabanlıdır.",
|
||||||
"author": "AITURK / TurkServis",
|
"author": "AITURK / TurkServis",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
Generated
+1
-1
@@ -65,7 +65,7 @@
|
|||||||
},
|
},
|
||||||
"apps/desktop": {
|
"apps/desktop": {
|
||||||
"name": "aiturk-ide",
|
"name": "aiturk-ide",
|
||||||
"version": "1.0.0-beta.33",
|
"version": "1.0.0-beta.34",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@assistant-ui/core": "0.2.23",
|
"@assistant-ui/core": "0.2.23",
|
||||||
|
|||||||
Reference in new issue
Block a user