agentram 0.1.9 → 0.1.11
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/README.md +40 -0
- package/agentram/cli.py +138 -32
- package/bin/agentram-postinstall.js +35 -0
- package/package.json +52 -51
- package/pyproject.toml +2 -2
package/README.md
CHANGED
|
@@ -998,3 +998,43 @@ Supervisor creates plan -> Main agent executes -> Small agent records RAM notes
|
|
|
998
998
|
```
|
|
999
999
|
|
|
1000
1000
|
Small agent should not own big direction. It records plans, decisions, files, risks, next tasks, and coding facts into RAM.
|
|
1001
|
+
|
|
1002
|
+
## Textual TUI
|
|
1003
|
+
|
|
1004
|
+
Install rich terminal UI with native scrollable chat pane:
|
|
1005
|
+
|
|
1006
|
+
```bash
|
|
1007
|
+
pip install agentram[tui]
|
|
1008
|
+
agentram tui
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
When `textual` is installed, AgentRAM uses a real full-screen TUI with mouse wheel scrolling inside the chat frame. If `textual` is missing, it falls back to the basic print-based terminal UI.
|
|
1012
|
+
|
|
1013
|
+
## npm Python Dependencies
|
|
1014
|
+
|
|
1015
|
+
When installed through npm, AgentRAM runs a `postinstall` step that tries to install Python TUI dependencies for the Python interpreter used by `agentram`:
|
|
1016
|
+
|
|
1017
|
+
```text
|
|
1018
|
+
textual>=0.80
|
|
1019
|
+
prompt_toolkit>=3.0
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
Set target Python before install when needed:
|
|
1023
|
+
|
|
1024
|
+
```powershell
|
|
1025
|
+
$env:PYTHON="C:\Users\admin\anaconda3\python.exe"
|
|
1026
|
+
npm install -g agentram@latest
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
Skip automatic Python dependency install:
|
|
1030
|
+
|
|
1031
|
+
```powershell
|
|
1032
|
+
$env:AGENTRAM_SKIP_PY_DEPS="1"
|
|
1033
|
+
npm install -g agentram@latest
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
If auto install fails, install manually:
|
|
1037
|
+
|
|
1038
|
+
```powershell
|
|
1039
|
+
python -m pip install textual prompt_toolkit
|
|
1040
|
+
```
|
package/agentram/cli.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
|
+
import asyncio
|
|
4
5
|
from concurrent.futures import ThreadPoolExecutor
|
|
5
6
|
import json
|
|
6
7
|
import os
|
|
@@ -44,10 +45,10 @@ SLASH_COMMANDS: list[tuple[str, str]] = [
|
|
|
44
45
|
("/workflow", "Show supervisor workflow agents"),
|
|
45
46
|
("/route on|off|status", "Toggle auto prompt routing"),
|
|
46
47
|
("/orchestrate <task>", "Build multi-model agent plan"),
|
|
47
|
-
("/ask <prompt>", "Execute bound models and return outputs"),
|
|
48
|
-
("/claude-install [path]", "Install .claude commands and agents"),
|
|
49
|
-
("/note <text>", "Save decision note"),
|
|
50
|
-
("/clear", "Clear chat"),
|
|
48
|
+
("/ask <prompt>", "Execute bound models and return outputs"),
|
|
49
|
+
("/claude-install [path]", "Install .claude commands and agents"),
|
|
50
|
+
("/note <text>", "Save decision note"),
|
|
51
|
+
("/clear", "Clear chat"),
|
|
51
52
|
("/exit", "Quit"),
|
|
52
53
|
("Plain text", "Capture coding chat message and retrieve context"),
|
|
53
54
|
]
|
|
@@ -76,9 +77,9 @@ SLASH_HELP = """Slash commands:
|
|
|
76
77
|
/route on|off|status Toggle auto prompt routing
|
|
77
78
|
/orchestrate <task> Build multi-model agent plan
|
|
78
79
|
/ask <prompt> Execute bound models and return outputs
|
|
79
|
-
/claude-install [path] Install .claude commands and agents
|
|
80
|
-
/note <text> Save decision note
|
|
81
|
-
/clear Clear chat
|
|
80
|
+
/claude-install [path] Install .claude commands and agents
|
|
81
|
+
/note <text> Save decision note
|
|
82
|
+
/clear Clear chat
|
|
82
83
|
/exit Quit
|
|
83
84
|
Plain text Capture coding chat message and retrieve context
|
|
84
85
|
""".strip()
|
|
@@ -237,34 +238,121 @@ def run_command(args: argparse.Namespace) -> int:
|
|
|
237
238
|
raise SystemExit(f"unknown command: {command}")
|
|
238
239
|
|
|
239
240
|
|
|
240
|
-
def run_tui(context: McpContext) -> None:
|
|
241
|
-
context
|
|
241
|
+
def run_tui(context: McpContext) -> None:
|
|
242
|
+
if run_textual_tui(context):
|
|
243
|
+
return
|
|
244
|
+
context.init_storage()
|
|
242
245
|
prompt_session = create_prompt_session()
|
|
243
246
|
input_hint = "live slash autocomplete enabled" if prompt_session else "basic input fallback; install prompt_toolkit for live slash dropdown"
|
|
244
|
-
messages = [
|
|
245
|
-
"system > AgentRAM coding-agent CLI ready",
|
|
246
|
-
f"system > RAM root: {context.ram_root}",
|
|
247
|
-
f"system > {input_hint}",
|
|
248
|
-
]
|
|
249
|
-
while True:
|
|
250
|
-
draw_screen(context, messages)
|
|
247
|
+
messages = [
|
|
248
|
+
"system > AgentRAM coding-agent CLI ready",
|
|
249
|
+
f"system > RAM root: {context.ram_root}",
|
|
250
|
+
f"system > {input_hint}",
|
|
251
|
+
]
|
|
252
|
+
while True:
|
|
253
|
+
draw_screen(context, messages)
|
|
251
254
|
try:
|
|
252
255
|
user_input = read_tui_input(prompt_session).strip()
|
|
253
256
|
except (EOFError, KeyboardInterrupt):
|
|
254
257
|
return
|
|
255
|
-
if user_input in {"0", "q", "quit", "exit", "/exit", "/quit"}:
|
|
256
|
-
return
|
|
257
|
-
if user_input in BUTTONS:
|
|
258
|
-
user_input = BUTTONS[user_input]
|
|
259
|
-
if user_input:
|
|
260
|
-
messages.append(f"user > {user_input}")
|
|
258
|
+
if user_input in {"0", "q", "quit", "exit", "/exit", "/quit"}:
|
|
259
|
+
return
|
|
260
|
+
if user_input in BUTTONS:
|
|
261
|
+
user_input = BUTTONS[user_input]
|
|
262
|
+
if user_input:
|
|
263
|
+
messages.append(f"user > {user_input}")
|
|
261
264
|
response = run_with_activity(context, messages, user_input)
|
|
262
265
|
if response == "__clear__":
|
|
263
266
|
messages.clear()
|
|
264
267
|
messages.append("system > Chat cleared.")
|
|
265
268
|
elif response:
|
|
266
269
|
messages.append("agentram > " + response)
|
|
267
|
-
del messages[:-
|
|
270
|
+
del messages[:-200]
|
|
271
|
+
|
|
272
|
+
def run_textual_tui(context: McpContext) -> bool:
|
|
273
|
+
try:
|
|
274
|
+
from textual.app import App, ComposeResult
|
|
275
|
+
from textual.containers import Horizontal, Vertical
|
|
276
|
+
from textual.widgets import Footer, Header, Input, RichLog, Static
|
|
277
|
+
except ImportError:
|
|
278
|
+
return False
|
|
279
|
+
|
|
280
|
+
class AgentRAMTextualApp(App[None]):
|
|
281
|
+
CSS = """
|
|
282
|
+
Screen { background: #0b0f14; color: #d7dde8; }
|
|
283
|
+
#layout { height: 1fr; }
|
|
284
|
+
#sidebar { width: 32; border: solid #263241; padding: 1; }
|
|
285
|
+
#main { width: 1fr; }
|
|
286
|
+
#chat { height: 1fr; border: solid #263241; padding: 1; overflow-y: scroll; }
|
|
287
|
+
#input { dock: bottom; border: solid #3b82f6; }
|
|
288
|
+
.muted { color: #8b9bb0; }
|
|
289
|
+
"""
|
|
290
|
+
BINDINGS = [("ctrl+c", "quit", "Quit")]
|
|
291
|
+
|
|
292
|
+
def __init__(self, mcp_context: McpContext) -> None:
|
|
293
|
+
super().__init__()
|
|
294
|
+
self.context = mcp_context
|
|
295
|
+
self.messages: list[str] = []
|
|
296
|
+
self.busy = False
|
|
297
|
+
|
|
298
|
+
def compose(self) -> ComposeResult:
|
|
299
|
+
yield Header(show_clock=True)
|
|
300
|
+
with Horizontal(id="layout"):
|
|
301
|
+
yield Static(id="sidebar")
|
|
302
|
+
with Vertical(id="main"):
|
|
303
|
+
yield RichLog(id="chat", wrap=True, highlight=True, markup=False, auto_scroll=True)
|
|
304
|
+
yield Input(placeholder="Prompt hoặc /command. Mouse wheel scroll trong khung chat.", id="input")
|
|
305
|
+
yield Footer()
|
|
306
|
+
|
|
307
|
+
def on_mount(self) -> None:
|
|
308
|
+
self.context.init_storage()
|
|
309
|
+
self.chat.write("system > AgentRAM Textual TUI ready")
|
|
310
|
+
self.chat.write(f"system > RAM root: {self.context.ram_root}")
|
|
311
|
+
self.refresh_sidebar()
|
|
312
|
+
self.set_interval(1.0, self.refresh_sidebar)
|
|
313
|
+
|
|
314
|
+
@property
|
|
315
|
+
def chat(self) -> RichLog:
|
|
316
|
+
return self.query_one("#chat", RichLog)
|
|
317
|
+
|
|
318
|
+
def refresh_sidebar(self) -> None:
|
|
319
|
+
self.query_one("#sidebar", Static).update("\n".join(sidebar_lines(self.context)))
|
|
320
|
+
|
|
321
|
+
async def on_input_submitted(self, event: Input.Submitted) -> None:
|
|
322
|
+
text = event.value.strip()
|
|
323
|
+
event.input.value = ""
|
|
324
|
+
if not text:
|
|
325
|
+
return
|
|
326
|
+
if text in {"0", "q", "quit", "exit", "/exit", "/quit"}:
|
|
327
|
+
self.exit()
|
|
328
|
+
return
|
|
329
|
+
if text in BUTTONS:
|
|
330
|
+
text = BUTTONS[text]
|
|
331
|
+
self.chat.write(f"user > {text}")
|
|
332
|
+
if text == "/clear":
|
|
333
|
+
self.chat.clear()
|
|
334
|
+
self.chat.write("system > Chat cleared.")
|
|
335
|
+
return
|
|
336
|
+
if self.busy:
|
|
337
|
+
self.chat.write("agentram > busy, wait current task")
|
|
338
|
+
return
|
|
339
|
+
self.busy = True
|
|
340
|
+
self.chat.write("agentram > thinking...")
|
|
341
|
+
try:
|
|
342
|
+
response = await asyncio.to_thread(handle_chat_input, self.context, text, self.messages)
|
|
343
|
+
except Exception as error: # noqa: BLE001 - TUI boundary
|
|
344
|
+
response = f"error: {error}"
|
|
345
|
+
finally:
|
|
346
|
+
self.busy = False
|
|
347
|
+
if response == "__clear__":
|
|
348
|
+
self.chat.clear()
|
|
349
|
+
self.chat.write("system > Chat cleared.")
|
|
350
|
+
elif response:
|
|
351
|
+
self.chat.write("agentram > " + response)
|
|
352
|
+
self.refresh_sidebar()
|
|
353
|
+
|
|
354
|
+
AgentRAMTextualApp(context).run()
|
|
355
|
+
return True
|
|
268
356
|
|
|
269
357
|
def run_with_activity(context: McpContext, messages: list[str], user_input: str) -> str:
|
|
270
358
|
with ThreadPoolExecutor(max_workers=1) as executor:
|
|
@@ -663,12 +751,7 @@ def supervisor_workflow_text(context: McpContext, prompt: str) -> str:
|
|
|
663
751
|
outputs[slot] = f"error: {model_error_hint(str(error))}"
|
|
664
752
|
if not main_agent:
|
|
665
753
|
outputs["main"] = "No main agent bound. Use /bind-agent main <provider> <model>."
|
|
666
|
-
|
|
667
|
-
call_tool(
|
|
668
|
-
context,
|
|
669
|
-
"agentram_emit_event",
|
|
670
|
-
{"type": "DECISION", "payload": {"content": outputs["small"]}, "task_id": "codex", "ingest": True},
|
|
671
|
-
)
|
|
754
|
+
persist_workflow_memory(context, prompt, plan, outputs)
|
|
672
755
|
return "\n".join(
|
|
673
756
|
[
|
|
674
757
|
"Workflow: supervisor -> main + small -> merge",
|
|
@@ -683,6 +766,28 @@ def supervisor_workflow_text(context: McpContext, prompt: str) -> str:
|
|
|
683
766
|
]
|
|
684
767
|
)
|
|
685
768
|
|
|
769
|
+
def persist_workflow_memory(context: McpContext, prompt: str, plan: str, outputs: dict[str, str]) -> None:
|
|
770
|
+
small_notes = outputs.get("small", "").strip()
|
|
771
|
+
main_result = outputs.get("main", "").strip()
|
|
772
|
+
note_parts = [
|
|
773
|
+
f"User request: {prompt}",
|
|
774
|
+
f"Supervisor plan: {trim(plan.strip(), 1200)}" if plan.strip() else "Supervisor plan: -",
|
|
775
|
+
]
|
|
776
|
+
if small_notes and not small_notes.startswith("error:"):
|
|
777
|
+
note_parts.append(f"Small memory notes: {trim(small_notes, 1200)}")
|
|
778
|
+
else:
|
|
779
|
+
note_parts.append("Small memory notes: unavailable; persisted supervisor plan as fallback RAM note.")
|
|
780
|
+
if main_result and not main_result.startswith("error:"):
|
|
781
|
+
note_parts.append(f"Main result summary: {trim(main_result, 600)}")
|
|
782
|
+
content = "\n".join(note_parts).strip()
|
|
783
|
+
if not content:
|
|
784
|
+
return
|
|
785
|
+
call_tool(
|
|
786
|
+
context,
|
|
787
|
+
"agentram_emit_event",
|
|
788
|
+
{"type": "DECISION", "payload": {"content": content}, "task_id": "codex", "ingest": True},
|
|
789
|
+
)
|
|
790
|
+
|
|
686
791
|
def supervisor_plan(supervisor: AgentModelEndpoint | None, prompt: str, memory_context: str) -> str:
|
|
687
792
|
if not supervisor:
|
|
688
793
|
return "No supervisor bound. Fallback plan: handle user request, run main coding agent, ask small agent to update RAM notes."
|
|
@@ -908,7 +1013,7 @@ def draw_screen(context: McpContext, messages: list[str], activity: str | None =
|
|
|
908
1013
|
print(box_text("◆ AgentRAM Code | RAM + Claude subagents + slash commands", width))
|
|
909
1014
|
print("+" + "-" * (width - 2) + "+")
|
|
910
1015
|
|
|
911
|
-
sidebar = sidebar_lines(context)
|
|
1016
|
+
sidebar = sidebar_lines(context)
|
|
912
1017
|
display_messages = [*messages, activity] if activity else messages
|
|
913
1018
|
chat = wrap_messages(display_messages, right_width - 4)[-22:]
|
|
914
1019
|
rows = max(len(sidebar), len(chat), 22)
|
|
@@ -917,7 +1022,7 @@ def draw_screen(context: McpContext, messages: list[str], activity: str | None =
|
|
|
917
1022
|
right = chat[index] if index < len(chat) else ""
|
|
918
1023
|
print("| " + left[: left_width - 2].ljust(left_width - 2) + "| " + right[: right_width - 2].ljust(right_width - 2) + "|")
|
|
919
1024
|
print("+" + "-" * (left_width - 1) + "+" + "-" * (right_width) + "+")
|
|
920
|
-
footer = "Thinking/acting..." if activity else "Input: type / for
|
|
1025
|
+
footer = "Thinking/acting..." if activity else "Input: type / for commands. Use mouse wheel or terminal scrollbar for previous output."
|
|
921
1026
|
print(box_text(footer, width))
|
|
922
1027
|
print("+" + "-" * (width - 2) + "+")
|
|
923
1028
|
|
|
@@ -957,7 +1062,8 @@ def sidebar_lines(context: McpContext) -> list[str]:
|
|
|
957
1062
|
" /ask <prompt>",
|
|
958
1063
|
]
|
|
959
1064
|
|
|
960
|
-
|
|
1065
|
+
|
|
1066
|
+
|
|
961
1067
|
def trim(text: str, limit: int) -> str:
|
|
962
1068
|
return text if len(text) <= limit else text[: limit - 1] + "…"
|
|
963
1069
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawnSync } = require("node:child_process");
|
|
3
|
+
|
|
4
|
+
if (process.env.AGENTRAM_SKIP_PY_DEPS === "1") {
|
|
5
|
+
console.log("AgentRAM: skip Python TUI deps because AGENTRAM_SKIP_PY_DEPS=1");
|
|
6
|
+
process.exit(0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const candidates = process.env.PYTHON ? [process.env.PYTHON] : ["python", ...(process.platform === "win32" ? ["py"] : [])];
|
|
10
|
+
const deps = ["textual>=0.80", "prompt_toolkit>=3.0"];
|
|
11
|
+
|
|
12
|
+
function runPython(command, args) {
|
|
13
|
+
const finalArgs = command === "py" ? ["-3", ...args] : args;
|
|
14
|
+
return spawnSync(command, finalArgs, { stdio: "inherit" });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let lastError = null;
|
|
18
|
+
for (const command of candidates) {
|
|
19
|
+
const probe = runPython(command, ["-c", "import sys; print(sys.executable)"]);
|
|
20
|
+
if (probe.error || probe.status !== 0) {
|
|
21
|
+
lastError = probe.error || new Error(`${command} exited ${probe.status}`);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
console.log(`AgentRAM: installing Python TUI deps with ${command}`);
|
|
25
|
+
const install = runPython(command, ["-m", "pip", "install", ...deps]);
|
|
26
|
+
if (!install.error && install.status === 0) {
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
lastError = install.error || new Error(`${command} pip install exited ${install.status}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.warn("AgentRAM: Python TUI deps were not installed automatically.");
|
|
33
|
+
console.warn("AgentRAM: run `python -m pip install textual prompt_toolkit` manually, or set PYTHON to the target interpreter.");
|
|
34
|
+
if (lastError) console.warn(`AgentRAM: ${lastError.message}`);
|
|
35
|
+
process.exit(process.env.AGENTRAM_STRICT_POSTINSTALL === "1" ? 1 : 0);
|
package/package.json
CHANGED
|
@@ -1,51 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agentram",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Async, model-agnostic Working RAM for coding agents.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"homepage": "https://github.com/trancongnghia/AGENT_RAM#readme",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/trancongnghia/AGENT_RAM.git"
|
|
10
|
-
},
|
|
11
|
-
"bugs": {
|
|
12
|
-
"url": "https://github.com/trancongnghia/AGENT_RAM/issues"
|
|
13
|
-
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"agent",
|
|
16
|
-
"memory",
|
|
17
|
-
"codex",
|
|
18
|
-
"claude",
|
|
19
|
-
"mcp",
|
|
20
|
-
"llm"
|
|
21
|
-
],
|
|
22
|
-
"bin": {
|
|
23
|
-
"agentram": "bin/agentram.js",
|
|
24
|
-
"agentram-mcp": "bin/agentram-mcp.js"
|
|
25
|
-
},
|
|
26
|
-
"scripts": {
|
|
27
|
-
"agentram": "node bin/agentram.js",
|
|
28
|
-
"agentram:mcp": "node bin/agentram-mcp.js",
|
|
29
|
-
"test": "python -m pytest -q",
|
|
30
|
-
"pack:dry-run": "npm pack --dry-run",
|
|
31
|
-
"prepublishOnly": "npm test"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
".claude/
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "agentram",
|
|
3
|
+
"version": "0.1.11",
|
|
4
|
+
"description": "Async, model-agnostic Working RAM for coding agents.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/trancongnghia/AGENT_RAM#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/trancongnghia/AGENT_RAM.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/trancongnghia/AGENT_RAM/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"agent",
|
|
16
|
+
"memory",
|
|
17
|
+
"codex",
|
|
18
|
+
"claude",
|
|
19
|
+
"mcp",
|
|
20
|
+
"llm"
|
|
21
|
+
],
|
|
22
|
+
"bin": {
|
|
23
|
+
"agentram": "bin/agentram.js",
|
|
24
|
+
"agentram-mcp": "bin/agentram-mcp.js"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"agentram": "node bin/agentram.js",
|
|
28
|
+
"agentram:mcp": "node bin/agentram-mcp.js",
|
|
29
|
+
"test": "python -m pytest -q",
|
|
30
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
31
|
+
"prepublishOnly": "npm test",
|
|
32
|
+
"postinstall": "node bin/agentram-postinstall.js"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"agentram/*.py",
|
|
36
|
+
"bin/*.js",
|
|
37
|
+
".claude/agents/*.md",
|
|
38
|
+
".claude/commands/*.md",
|
|
39
|
+
"agentram_mcp_server.py",
|
|
40
|
+
"agentram_daemon.py",
|
|
41
|
+
"codex_ram.py",
|
|
42
|
+
"pyproject.toml",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=16"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
}
|
|
52
|
+
}
|
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
|
+
version = "0.1.11"
|
|
8
8
|
description = "Async, model-agnostic RAM layer for agentic coding tools."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -22,7 +22,7 @@ requires-python = ">=3.10"
|
|
|
22
22
|
dependencies = []
|
|
23
23
|
|
|
24
24
|
[project.optional-dependencies]
|
|
25
|
-
tui = ["prompt_toolkit>=3.0"]
|
|
25
|
+
tui = ["prompt_toolkit>=3.0", "textual>=0.80"]
|
|
26
26
|
|
|
27
27
|
[project.urls]
|
|
28
28
|
Homepage = "https://github.com/your-org/agentram"
|