abstractcode 0.2.0__py3-none-any.whl → 0.3.1__py3-none-any.whl
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.
- abstractcode/__init__.py +1 -1
- abstractcode/cli.py +911 -9
- abstractcode/file_mentions.py +276 -0
- abstractcode/flow_cli.py +1413 -0
- abstractcode/fullscreen_ui.py +2473 -158
- abstractcode/gateway_cli.py +715 -0
- abstractcode/py.typed +1 -0
- abstractcode/react_shell.py +8140 -546
- abstractcode/recall.py +384 -0
- abstractcode/remember.py +184 -0
- abstractcode/terminal_markdown.py +557 -0
- abstractcode/theme.py +244 -0
- abstractcode/workflow_agent.py +1412 -0
- abstractcode/workflow_cli.py +229 -0
- abstractcode-0.3.1.dist-info/METADATA +158 -0
- abstractcode-0.3.1.dist-info/RECORD +21 -0
- {abstractcode-0.2.0.dist-info → abstractcode-0.3.1.dist-info}/WHEEL +1 -1
- abstractcode-0.2.0.dist-info/METADATA +0 -160
- abstractcode-0.2.0.dist-info/RECORD +0 -11
- {abstractcode-0.2.0.dist-info → abstractcode-0.3.1.dist-info}/entry_points.txt +0 -0
- {abstractcode-0.2.0.dist-info → abstractcode-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {abstractcode-0.2.0.dist-info → abstractcode-0.3.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _gateway_api(*, gateway_url: Optional[str], gateway_token: Optional[str]):
|
|
8
|
+
from .gateway_cli import GatewayApi, default_gateway_token, default_gateway_url
|
|
9
|
+
|
|
10
|
+
url = str(gateway_url or "").strip() or default_gateway_url()
|
|
11
|
+
token_raw = str(gateway_token or "").strip()
|
|
12
|
+
token = token_raw if token_raw else default_gateway_token()
|
|
13
|
+
return GatewayApi(base_url=url, token=token)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def install_workflow_bundle_command(
|
|
17
|
+
*,
|
|
18
|
+
source: str,
|
|
19
|
+
gateway_url: Optional[str] = None,
|
|
20
|
+
gateway_token: Optional[str] = None,
|
|
21
|
+
overwrite: bool = False,
|
|
22
|
+
output_json: bool = False,
|
|
23
|
+
) -> dict[str, Any]:
|
|
24
|
+
api = _gateway_api(gateway_url=gateway_url, gateway_token=gateway_token)
|
|
25
|
+
try:
|
|
26
|
+
resp = api.upload_bundle(path=source, overwrite=bool(overwrite), reload=True)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
return {"ok": False, "error": str(e)}
|
|
29
|
+
|
|
30
|
+
out = dict(resp or {})
|
|
31
|
+
out.setdefault("gateway_url", str(getattr(api, "base_url", "") or ""))
|
|
32
|
+
if output_json:
|
|
33
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
34
|
+
else:
|
|
35
|
+
bref = str(out.get("bundle_ref") or "").strip() or str(out.get("bundle_id") or "").strip() or "?"
|
|
36
|
+
print(f"Installed on gateway: {bref}")
|
|
37
|
+
return out
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def list_workflow_bundles_command(
|
|
41
|
+
*,
|
|
42
|
+
gateway_url: Optional[str] = None,
|
|
43
|
+
gateway_token: Optional[str] = None,
|
|
44
|
+
interface: Optional[str] = None,
|
|
45
|
+
all_versions: bool = False,
|
|
46
|
+
include_deprecated: bool = False,
|
|
47
|
+
output_json: bool = False,
|
|
48
|
+
) -> dict[str, Any]:
|
|
49
|
+
api = _gateway_api(gateway_url=gateway_url, gateway_token=gateway_token)
|
|
50
|
+
try:
|
|
51
|
+
resp = api.list_bundles(all_versions=bool(all_versions), include_deprecated=bool(include_deprecated))
|
|
52
|
+
except Exception as e:
|
|
53
|
+
return {"ok": False, "error": str(e)}
|
|
54
|
+
|
|
55
|
+
bundles_raw = resp.get("items") if isinstance(resp, dict) and isinstance(resp.get("items"), list) else []
|
|
56
|
+
items: list[dict[str, Any]] = []
|
|
57
|
+
for b in bundles_raw:
|
|
58
|
+
if not isinstance(b, dict):
|
|
59
|
+
continue
|
|
60
|
+
bid = str(b.get("bundle_id") or "").strip()
|
|
61
|
+
bver = str(b.get("bundle_version") or "").strip()
|
|
62
|
+
bref = str(b.get("bundle_ref") or "").strip() or (f"{bid}@{bver}" if bid and bver else bid)
|
|
63
|
+
eps_raw = b.get("entrypoints") if isinstance(b.get("entrypoints"), list) else []
|
|
64
|
+
default_fid = str(b.get("default_entrypoint") or "").strip()
|
|
65
|
+
implied_default = len(eps_raw) == 1
|
|
66
|
+
for ep in eps_raw:
|
|
67
|
+
if not isinstance(ep, dict):
|
|
68
|
+
continue
|
|
69
|
+
fid = str(ep.get("flow_id") or "").strip()
|
|
70
|
+
if not fid:
|
|
71
|
+
continue
|
|
72
|
+
deprecated = bool(ep.get("deprecated") is True)
|
|
73
|
+
interfaces = [str(x).strip() for x in list(ep.get("interfaces") or []) if isinstance(x, str) and x.strip()]
|
|
74
|
+
if interface and interface not in interfaces:
|
|
75
|
+
continue
|
|
76
|
+
items.append(
|
|
77
|
+
{
|
|
78
|
+
"bundle_id": bid,
|
|
79
|
+
"bundle_version": bver,
|
|
80
|
+
"bundle_ref": bref,
|
|
81
|
+
"workflow_id": f"{bref}:{fid}" if bref and fid else None,
|
|
82
|
+
"flow_id": fid,
|
|
83
|
+
"name": str(ep.get("name") or "") or fid,
|
|
84
|
+
"description": str(ep.get("description") or "") or "",
|
|
85
|
+
"interfaces": interfaces,
|
|
86
|
+
"default": bool(implied_default or (default_fid and fid == default_fid)),
|
|
87
|
+
"deprecated": bool(deprecated),
|
|
88
|
+
"deprecated_reason": str(ep.get("deprecated_reason") or "") or "",
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
items.sort(key=lambda x: (str(x.get("bundle_id") or ""), str(x.get("bundle_version") or ""), str(x.get("flow_id") or "")))
|
|
93
|
+
out = {"ok": True, "gateway_url": str(getattr(api, "base_url", "") or ""), "count": len(items), "entrypoints": items}
|
|
94
|
+
if output_json:
|
|
95
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
96
|
+
else:
|
|
97
|
+
if not items:
|
|
98
|
+
print("No workflows found on the gateway.")
|
|
99
|
+
for it in items:
|
|
100
|
+
name = it.get("name") or it.get("workflow_id") or ""
|
|
101
|
+
iface = ""
|
|
102
|
+
interfaces = it.get("interfaces") or []
|
|
103
|
+
if isinstance(interfaces, list) and interfaces:
|
|
104
|
+
iface = f" [{', '.join(interfaces)}]"
|
|
105
|
+
default = " *" if it.get("default") else ""
|
|
106
|
+
dep = " (deprecated)" if it.get("deprecated") else ""
|
|
107
|
+
wid = str(it.get("workflow_id") or it.get("bundle_ref") or "")
|
|
108
|
+
print(f"{wid}{default}{dep} {name}{iface}")
|
|
109
|
+
return out
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def workflow_bundle_info_command(
|
|
113
|
+
*,
|
|
114
|
+
bundle_ref: str,
|
|
115
|
+
gateway_url: Optional[str] = None,
|
|
116
|
+
gateway_token: Optional[str] = None,
|
|
117
|
+
output_json: bool = False,
|
|
118
|
+
) -> dict[str, Any]:
|
|
119
|
+
api = _gateway_api(gateway_url=gateway_url, gateway_token=gateway_token)
|
|
120
|
+
ref = str(bundle_ref or "").strip()
|
|
121
|
+
if not ref:
|
|
122
|
+
return {"ok": False, "error": "bundle_ref is required"}
|
|
123
|
+
bid, ver = (ref.split("@", 1) + [""])[:2] if "@" in ref else (ref, "")
|
|
124
|
+
ver2 = ver.strip() or None
|
|
125
|
+
try:
|
|
126
|
+
resp = api.get_bundle(bundle_id=str(bid).strip(), bundle_version=ver2)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
return {"ok": False, "error": str(e)}
|
|
129
|
+
|
|
130
|
+
out = dict(resp or {})
|
|
131
|
+
out.setdefault("ok", True)
|
|
132
|
+
out.setdefault("gateway_url", str(getattr(api, "base_url", "") or ""))
|
|
133
|
+
if output_json:
|
|
134
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
135
|
+
else:
|
|
136
|
+
bref = str(out.get("bundle_ref") or out.get("bundle_id") or "").strip()
|
|
137
|
+
print(bref or ref)
|
|
138
|
+
de = out.get("default_entrypoint")
|
|
139
|
+
if isinstance(de, str) and de.strip():
|
|
140
|
+
print(f"default: {de.strip()}")
|
|
141
|
+
eps = out.get("entrypoints") if isinstance(out.get("entrypoints"), list) else []
|
|
142
|
+
for ep in eps:
|
|
143
|
+
if not isinstance(ep, dict):
|
|
144
|
+
continue
|
|
145
|
+
fid = str(ep.get("flow_id") or "").strip()
|
|
146
|
+
name = str(ep.get("name") or "").strip() or fid
|
|
147
|
+
if fid:
|
|
148
|
+
print(f"- {fid} {name}")
|
|
149
|
+
return out
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def remove_workflow_bundle_command(
|
|
153
|
+
*,
|
|
154
|
+
bundle_ref: str,
|
|
155
|
+
gateway_url: Optional[str] = None,
|
|
156
|
+
gateway_token: Optional[str] = None,
|
|
157
|
+
output_json: bool = False,
|
|
158
|
+
) -> dict[str, Any]:
|
|
159
|
+
api = _gateway_api(gateway_url=gateway_url, gateway_token=gateway_token)
|
|
160
|
+
try:
|
|
161
|
+
resp = api.remove_bundle(bundle_ref=str(bundle_ref or "").strip(), reload=True)
|
|
162
|
+
except Exception as e:
|
|
163
|
+
return {"ok": False, "error": str(e)}
|
|
164
|
+
|
|
165
|
+
out = dict(resp or {})
|
|
166
|
+
out.setdefault("gateway_url", str(getattr(api, "base_url", "") or ""))
|
|
167
|
+
if output_json:
|
|
168
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
169
|
+
else:
|
|
170
|
+
removed = out.get("removed")
|
|
171
|
+
bref = str(out.get("bundle_ref") or bundle_ref or "").strip() or "?"
|
|
172
|
+
print(f"Removed {removed} bundle(s) from gateway for {bref}")
|
|
173
|
+
return out
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def deprecate_workflow_bundle_command(
|
|
177
|
+
*,
|
|
178
|
+
bundle_id: str,
|
|
179
|
+
flow_id: Optional[str] = None,
|
|
180
|
+
reason: Optional[str] = None,
|
|
181
|
+
gateway_url: Optional[str] = None,
|
|
182
|
+
gateway_token: Optional[str] = None,
|
|
183
|
+
output_json: bool = False,
|
|
184
|
+
) -> dict[str, Any]:
|
|
185
|
+
api = _gateway_api(gateway_url=gateway_url, gateway_token=gateway_token)
|
|
186
|
+
bid = str(bundle_id or "").strip()
|
|
187
|
+
if not bid:
|
|
188
|
+
return {"ok": False, "error": "bundle_id is required"}
|
|
189
|
+
try:
|
|
190
|
+
resp = api.deprecate_bundle(bundle_id=bid, flow_id=flow_id, reason=reason)
|
|
191
|
+
except Exception as e:
|
|
192
|
+
return {"ok": False, "error": str(e)}
|
|
193
|
+
|
|
194
|
+
out = dict(resp or {})
|
|
195
|
+
out.setdefault("gateway_url", str(getattr(api, "base_url", "") or ""))
|
|
196
|
+
if output_json:
|
|
197
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
198
|
+
else:
|
|
199
|
+
fid = str(out.get("flow_id") or "").strip() or "*"
|
|
200
|
+
print(f"Deprecated on gateway: {bid}:{fid}")
|
|
201
|
+
return out
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def undeprecate_workflow_bundle_command(
|
|
205
|
+
*,
|
|
206
|
+
bundle_id: str,
|
|
207
|
+
flow_id: Optional[str] = None,
|
|
208
|
+
gateway_url: Optional[str] = None,
|
|
209
|
+
gateway_token: Optional[str] = None,
|
|
210
|
+
output_json: bool = False,
|
|
211
|
+
) -> dict[str, Any]:
|
|
212
|
+
api = _gateway_api(gateway_url=gateway_url, gateway_token=gateway_token)
|
|
213
|
+
bid = str(bundle_id or "").strip()
|
|
214
|
+
if not bid:
|
|
215
|
+
return {"ok": False, "error": "bundle_id is required"}
|
|
216
|
+
try:
|
|
217
|
+
resp = api.undeprecate_bundle(bundle_id=bid, flow_id=flow_id)
|
|
218
|
+
except Exception as e:
|
|
219
|
+
return {"ok": False, "error": str(e)}
|
|
220
|
+
|
|
221
|
+
out = dict(resp or {})
|
|
222
|
+
out.setdefault("gateway_url", str(getattr(api, "base_url", "") or ""))
|
|
223
|
+
if output_json:
|
|
224
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
225
|
+
else:
|
|
226
|
+
fid = str(out.get("flow_id") or "").strip() or "*"
|
|
227
|
+
removed = bool(out.get("removed") is True)
|
|
228
|
+
print(f"Undeprecated on gateway: {bid}:{fid} ({'changed' if removed else 'no-op'})")
|
|
229
|
+
return out
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: abstractcode
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: A clean terminal CLI for multi-agent agentic coding
|
|
5
|
+
Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
6
|
+
Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://abstractcore.ai
|
|
9
|
+
Project-URL: Documentation, https://abstractcore.ai
|
|
10
|
+
Project-URL: Repository, https://github.com/lpalbou/abstractcode
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/lpalbou/abstractcode/issues
|
|
12
|
+
Keywords: ai,llm,cli,coding,agent,multi-agent,agentic,terminal,abstractcore,abstractruntime,abstractagent
|
|
13
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: abstractagent>=0.2.0
|
|
27
|
+
Requires-Dist: abstractruntime>=0.2.0
|
|
28
|
+
Requires-Dist: abstractcore[tools]>=2.6.8
|
|
29
|
+
Requires-Dist: ddgs<10.0.0,>=9.10.0
|
|
30
|
+
Requires-Dist: prompt_toolkit>=3.0.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Provides-Extra: flow
|
|
37
|
+
Requires-Dist: abstractflow>=0.1.0; extra == "flow"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# AbstractCode
|
|
41
|
+
|
|
42
|
+
Durable terminal TUI for agentic coding on the Abstract* stack (**AbstractAgent + AbstractRuntime + AbstractCore**).
|
|
43
|
+
|
|
44
|
+
Status: **pre-alpha** (APIs and UX may change).
|
|
45
|
+
|
|
46
|
+
Next: [`docs/getting-started.md`](docs/getting-started.md).
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- Interactive TUI (`abstractcode`) with **durable runs** (resume/pause/cancel), snapshots, and logs
|
|
51
|
+
- **Approval-gated tools** by default (with an allowlist you can configure)
|
|
52
|
+
- Built-in agents: `react`, `memact`, `codeact`
|
|
53
|
+
- VisualFlow workflows:
|
|
54
|
+
- run locally: `abstractcode flow ...` (optional extra)
|
|
55
|
+
- run as an agent: `abstractcode --agent <flow_ref>`
|
|
56
|
+
- Remote tool execution via **MCP** (`/mcp`, `/executor`)
|
|
57
|
+
- Optional gateway-first Web UI in `web/`
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
Python: **3.10+**
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install abstractcode
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Optional (run VisualFlow locally via `abstractcode flow ...`):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install "abstractcode[flow]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
From source (development):
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install -e ".[dev]"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quickstart (TUI)
|
|
80
|
+
|
|
81
|
+
Ollama (default provider):
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
abstractcode --provider ollama --model qwen3:1.7b-q4_K_M
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
OpenAI-compatible server (e.g. LM Studio):
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
abstractcode --provider openai --base-url http://127.0.0.1:1234/v1 --model qwen/qwen3-next-80b
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Inside the app:
|
|
94
|
+
- `/help` shows the authoritative command list
|
|
95
|
+
- type a task (or use `/task ...`)
|
|
96
|
+
- tool approvals: `/auto-accept` (or start with `--auto-approve`)
|
|
97
|
+
- attach files with `@path/to/file` in your prompt
|
|
98
|
+
|
|
99
|
+
## Persistence (durable runs)
|
|
100
|
+
|
|
101
|
+
Default paths:
|
|
102
|
+
- state file: `~/.abstractcode/state.json`
|
|
103
|
+
- durable stores: `~/.abstractcode/state.d/`
|
|
104
|
+
- saved settings: `~/.abstractcode/state.config.json`
|
|
105
|
+
|
|
106
|
+
Disable persistence:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
abstractcode --no-state
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Workflows
|
|
113
|
+
|
|
114
|
+
- Local runs: `abstractcode flow run <flow_id_or_path> ...` (requires `abstractcode[flow]`)
|
|
115
|
+
- Workflow agent: `abstractcode --agent /path/to/workflow.json ...`
|
|
116
|
+
- Remote control-plane: `abstractcode gateway --help`
|
|
117
|
+
- Bundle management on a gateway: `abstractcode workflow --help`
|
|
118
|
+
|
|
119
|
+
Details: [`docs/workflows.md`](docs/workflows.md).
|
|
120
|
+
|
|
121
|
+
## Web UI
|
|
122
|
+
|
|
123
|
+
The web host lives in `web/` and connects to an `abstractgateway` at `/api/gateway/*`.
|
|
124
|
+
|
|
125
|
+
Start here:
|
|
126
|
+
- [`docs/web.md`](docs/web.md)
|
|
127
|
+
- [`docs/deployment-web.md`](docs/deployment-web.md)
|
|
128
|
+
|
|
129
|
+
## Documentation
|
|
130
|
+
|
|
131
|
+
- Start here: [`docs/getting-started.md`](docs/getting-started.md)
|
|
132
|
+
- FAQ: [`docs/faq.md`](docs/faq.md)
|
|
133
|
+
- Docs index: [`docs/README.md`](docs/README.md)
|
|
134
|
+
- [`docs/architecture.md`](docs/architecture.md)
|
|
135
|
+
- [`docs/cli.md`](docs/cli.md)
|
|
136
|
+
- [`docs/api.md`](docs/api.md)
|
|
137
|
+
- [`docs/workflows.md`](docs/workflows.md)
|
|
138
|
+
- [`docs/ui_events.md`](docs/ui_events.md)
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
pip install -e ".[dev]"
|
|
144
|
+
pytest -q
|
|
145
|
+
ruff check .
|
|
146
|
+
black .
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Project
|
|
150
|
+
|
|
151
|
+
- Changelog: [`CHANGELOG.md`](CHANGELOG.md)
|
|
152
|
+
- Contributing: [`CONTRIBUTING.md`](CONTRIBUTING.md)
|
|
153
|
+
- Security: [`SECURITY.md`](SECURITY.md)
|
|
154
|
+
- Acknowledgments: [`ACKNOWLEDMENTS.md`](ACKNOWLEDMENTS.md)
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
abstractcode/__init__.py,sha256=O-DbZctdBATghwjZUCeHBYwe84a5wuRK6cd4z3kkyzg,658
|
|
2
|
+
abstractcode/cli.py,sha256=khWE6AP6BTYU6r8geXi_Lx5ocJ9lTbeuKukkre1hbts,42183
|
|
3
|
+
abstractcode/file_mentions.py,sha256=KFtFX_Ofjk_9r9Nirt1IXKLWr1VsSrXimHnRYxxvRYs,8664
|
|
4
|
+
abstractcode/flow_cli.py,sha256=CQq1g4rFylSW7y8ZZeQYmfroAXG1dDtmuOF8tc1BF2Y,49235
|
|
5
|
+
abstractcode/fullscreen_ui.py,sha256=rcYETwA5nMFNE1cNgIDTF3zUFLlqtJoveQ2W6feR7Ao,117536
|
|
6
|
+
abstractcode/gateway_cli.py,sha256=ajAYI0IUK3FBAVx5HdDh_zThyU7-tABre8meAUuO_cU,25251
|
|
7
|
+
abstractcode/input_handler.py,sha256=W2ImW4Yr3HMMD5SNPZOZJendVL-CRdYR5idXTWroxAY,2240
|
|
8
|
+
abstractcode/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
9
|
+
abstractcode/react_shell.py,sha256=lgydDok2ZgNwVDForvAYT9MxVYk7SiVmuUFMnYEOpvg,387224
|
|
10
|
+
abstractcode/recall.py,sha256=xu-xz8-kvkmAW6pKoAIcwox5jHWMBfBKExsA8fgwg_A,13040
|
|
11
|
+
abstractcode/remember.py,sha256=cmJlw-nR0OvK7tkN5B0sZSMaYlECl_tAyO34c-IL0Uo,6158
|
|
12
|
+
abstractcode/terminal_markdown.py,sha256=mL3YdBZt25DoJec23EXgve2zH4OMDJLxBnQfWvsSSh0,21465
|
|
13
|
+
abstractcode/theme.py,sha256=WWlMsbqIj4Z-jylOTnmV_zTirf87tdbrlrRsIaTBfQE,6689
|
|
14
|
+
abstractcode/workflow_agent.py,sha256=J8pw7r79lJZ58aqMXsRTabbgxEJzIlJHb8__oUPg_08,56744
|
|
15
|
+
abstractcode/workflow_cli.py,sha256=gabA7RzPe9-qkI3MSaRCrxErWeCl1faRa-oTGULxp_w,8936
|
|
16
|
+
abstractcode-0.3.1.dist-info/licenses/LICENSE,sha256=f8z-PbFM_xH0eqLsha8_nEg1jbm1eVtC2NNjtXhtuCo,1080
|
|
17
|
+
abstractcode-0.3.1.dist-info/METADATA,sha256=cdTyNM10_naY7dHmWc9oQmVWVOKqm8m2nkM52xi7c4w,4657
|
|
18
|
+
abstractcode-0.3.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
19
|
+
abstractcode-0.3.1.dist-info/entry_points.txt,sha256=M4AOKb4h2vKWy5OMg-czeJE2aXunVKlljUPN8BUtwoE,51
|
|
20
|
+
abstractcode-0.3.1.dist-info/top_level.txt,sha256=n9Hfv6cnmL55HoxXsA3V1YLbQxYAr58-UMLbdr-FCNw,13
|
|
21
|
+
abstractcode-0.3.1.dist-info/RECORD,,
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: abstractcode
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: A clean terminal CLI for multi-agent agentic coding
|
|
5
|
-
Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
6
|
-
Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
7
|
-
License: MIT
|
|
8
|
-
Project-URL: Homepage, https://abstractcore.ai
|
|
9
|
-
Project-URL: Documentation, https://abstractcore.ai
|
|
10
|
-
Project-URL: Repository, https://github.com/lpalbou/abstractcode
|
|
11
|
-
Project-URL: Bug Tracker, https://github.com/lpalbou/abstractcode/issues
|
|
12
|
-
Keywords: ai,llm,cli,coding,agent,multi-agent,agentic,terminal,abstractcore,abstractruntime,abstractagent
|
|
13
|
-
Classifier: Development Status :: 2 - Pre-Alpha
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
-
Classifier: Operating System :: OS Independent
|
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
-
Requires-Python: >=3.8
|
|
26
|
-
Description-Content-Type: text/markdown
|
|
27
|
-
License-File: LICENSE
|
|
28
|
-
Requires-Dist: prompt_toolkit>=3.0.0
|
|
29
|
-
Provides-Extra: dev
|
|
30
|
-
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
|
-
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
32
|
-
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
33
|
-
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
34
|
-
Dynamic: license-file
|
|
35
|
-
|
|
36
|
-
# AbstractCode
|
|
37
|
-
|
|
38
|
-
**A clean terminal CLI for multi-agent agentic coding**
|
|
39
|
-
|
|
40
|
-
[](https://opensource.org/licenses/MIT)
|
|
41
|
-
[](https://www.python.org/downloads/)
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Status
|
|
46
|
-
|
|
47
|
-
AbstractCode is under active development. A minimal interactive shell exists to support manual testing of AbstractAgent workflows.
|
|
48
|
-
|
|
49
|
-
Note: the PyPI release may lag behind the monorepo. For the latest development version, install from source.
|
|
50
|
-
|
|
51
|
-
## What is AbstractCode?
|
|
52
|
-
|
|
53
|
-
AbstractCode is a clean terminal CLI for multi-agent agentic coding, similar to Claude Code, Codex, and Gemini CLI. It leverages the powerful Abstract Framework ecosystem to provide seamless AI-powered coding assistance directly in your terminal.
|
|
54
|
-
|
|
55
|
-
## The Abstract Framework
|
|
56
|
-
|
|
57
|
-
AbstractCode is built on top of the Abstract Framework, a comprehensive suite of tools for AI-powered development:
|
|
58
|
-
|
|
59
|
-
- **[AbstractCore](https://github.com/lpalbou/abstractcore)** - Unified interface for multiple LLM providers
|
|
60
|
-
- **[AbstractRuntime](https://github.com/lpalbou/abstractruntime)** - Runtime environment for AI agents
|
|
61
|
-
- **[AbstractAgent](https://github.com/lpalbou/abstractagent)** - Multi-agent orchestration and coordination
|
|
62
|
-
|
|
63
|
-
## Features (Coming Soon)
|
|
64
|
-
|
|
65
|
-
- 🤖 **Multi-Agent Coding** - Coordinate multiple AI agents for complex coding tasks
|
|
66
|
-
- 🔌 **Provider Agnostic** - Works with OpenAI, Anthropic, Ollama, and more
|
|
67
|
-
- 💻 **Terminal Native** - Clean CLI interface for seamless workflow integration
|
|
68
|
-
- 🎯 **Context Aware** - Understands your codebase and project structure
|
|
69
|
-
- 🔄 **Iterative Development** - Collaborative coding with AI assistance
|
|
70
|
-
- 🌐 **Offline Capable** - Works with local models via Ollama
|
|
71
|
-
|
|
72
|
-
## Installation
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
pip install abstractcode
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Quick Start
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
# Show options
|
|
82
|
-
abstractcode --help
|
|
83
|
-
|
|
84
|
-
# Durable resume is enabled by default (state file: ~/.abstractcode/state.json)
|
|
85
|
-
# Override with:
|
|
86
|
-
ABSTRACTCODE_STATE_FILE=.abstractcode.state.json abstractcode
|
|
87
|
-
|
|
88
|
-
# Or disable persistence (in-memory only; cannot resume after quitting)
|
|
89
|
-
abstractcode --no-state
|
|
90
|
-
|
|
91
|
-
# Auto-approve tool calls (unsafe; bypasses interactive approvals)
|
|
92
|
-
abstractcode --auto-approve
|
|
93
|
-
|
|
94
|
-
# Limit agent iterations per task (default: 20)
|
|
95
|
-
abstractcode --max-iterations 25
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Notes:
|
|
99
|
-
- Run resume state is stored next to the state file in `*.d/`.
|
|
100
|
-
- Conversation history is stored in the run state (`RunState.vars["context"]["messages"]`) inside `*.d/`, and AbstractCode keeps the state file pointing at the most recent run so restarts can reload context.
|
|
101
|
-
- In the interactive shell, commands are slash-prefixed (e.g. `/help`, `/status`, `/history`, `/task ...`).
|
|
102
|
-
|
|
103
|
-
## Development (Monorepo)
|
|
104
|
-
|
|
105
|
-
From the monorepo root:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
pip install -e ./abstractcore -e ./abstractruntime -e ./abstractagent -e ./abstractcode
|
|
109
|
-
abstractcode --help
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Requirements
|
|
113
|
-
|
|
114
|
-
- Python 3.8 or higher
|
|
115
|
-
- AbstractCore
|
|
116
|
-
- AbstractRuntime
|
|
117
|
-
- AbstractAgent
|
|
118
|
-
|
|
119
|
-
## Documentation
|
|
120
|
-
|
|
121
|
-
Full documentation will be available at [abstractcore.ai](https://abstractcore.ai)
|
|
122
|
-
|
|
123
|
-
## Development Status
|
|
124
|
-
|
|
125
|
-
This project is in early development. Stay tuned for updates!
|
|
126
|
-
|
|
127
|
-
## Contributing
|
|
128
|
-
|
|
129
|
-
Contributions are welcome! Please check back soon for contribution guidelines.
|
|
130
|
-
|
|
131
|
-
## Contact
|
|
132
|
-
|
|
133
|
-
**Maintainer:** Laurent-Philippe Albou
|
|
134
|
-
📧 Email: contact@abstractcore.ai
|
|
135
|
-
🌐 Website: [abstractcore.ai](https://abstractcore.ai)
|
|
136
|
-
|
|
137
|
-
## License
|
|
138
|
-
|
|
139
|
-
MIT License - see LICENSE file for details.
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
**AbstractCode** - Multi-agent agentic coding in your terminal, powered by the Abstract Framework.
|
|
144
|
-
|
|
145
|
-
## Default Tools
|
|
146
|
-
|
|
147
|
-
AbstractCode provides a curated set of 8 tools for coding tasks:
|
|
148
|
-
|
|
149
|
-
| Tool | Description |
|
|
150
|
-
|------|-------------|
|
|
151
|
-
| `list_files` | Find and list files using glob patterns (case-insensitive) |
|
|
152
|
-
| `search_files` | Search for text patterns inside files using regex |
|
|
153
|
-
| `read_file` | Read file contents with optional line range |
|
|
154
|
-
| `write_file` | Write content to files, creating directories as needed |
|
|
155
|
-
| `edit_file` | Edit files by replacing text patterns (supports regex, line ranges, preview mode) |
|
|
156
|
-
| `execute_command` | Execute shell commands with security controls |
|
|
157
|
-
| `web_search` | Search the web via DuckDuckGo (no API key required) |
|
|
158
|
-
| `self_improve` | Log improvement suggestions for later review |
|
|
159
|
-
|
|
160
|
-
Additional tools are available via AbstractAgent for specialized use cases (execute_python, fetch_url).
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
abstractcode/__init__.py,sha256=pHrawn8KtpITMmArbfOQBm1WrGKL7qMAr0cu81ianDU,658
|
|
2
|
-
abstractcode/cli.py,sha256=oW9S7eZlsIFP2yF9TtlTi6vaUF120uqanLnsntoSSL0,3438
|
|
3
|
-
abstractcode/fullscreen_ui.py,sha256=-7xOhz657TXjZvcQeCzJ3RfzyaEuTzXI6e5uge7U0V4,23951
|
|
4
|
-
abstractcode/input_handler.py,sha256=W2ImW4Yr3HMMD5SNPZOZJendVL-CRdYR5idXTWroxAY,2240
|
|
5
|
-
abstractcode/react_shell.py,sha256=fOLiTJje3IeJ0LjAyye_vsN6m7CLNx9R6skDGXN2258,50699
|
|
6
|
-
abstractcode-0.2.0.dist-info/licenses/LICENSE,sha256=f8z-PbFM_xH0eqLsha8_nEg1jbm1eVtC2NNjtXhtuCo,1080
|
|
7
|
-
abstractcode-0.2.0.dist-info/METADATA,sha256=38oM_FIIMKz2jpCxKOg4fA_vnLv8OD3v2zDUtmC_TME,5985
|
|
8
|
-
abstractcode-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
-
abstractcode-0.2.0.dist-info/entry_points.txt,sha256=M4AOKb4h2vKWy5OMg-czeJE2aXunVKlljUPN8BUtwoE,51
|
|
10
|
-
abstractcode-0.2.0.dist-info/top_level.txt,sha256=n9Hfv6cnmL55HoxXsA3V1YLbQxYAr58-UMLbdr-FCNw,13
|
|
11
|
-
abstractcode-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|