cortexdb-cli 0.2.0__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.
cortexdb_cli/output.py ADDED
@@ -0,0 +1,399 @@
1
+ """Output formatting for CortexDB CLI.
2
+
3
+ Two modes:
4
+ - Rich mode (TTY): colored panels, tables, spinners
5
+ - JSON mode (pipe/--json): machine-readable JSON to stdout
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import sys
12
+ from contextlib import contextmanager
13
+ from datetime import datetime, timezone
14
+ from typing import Any, Generator
15
+
16
+ from rich.console import Console
17
+ from rich.markup import escape
18
+ from rich.panel import Panel
19
+ from rich.table import Table
20
+ from rich.text import Text
21
+ from rich.theme import Theme
22
+
23
+ THEME = Theme({
24
+ "info": "cyan",
25
+ "success": "green bold",
26
+ "warning": "yellow",
27
+ "error": "red bold",
28
+ "dim": "dim",
29
+ "score.high": "green bold",
30
+ "score.mid": "yellow",
31
+ "score.low": "red",
32
+ "header": "bold magenta",
33
+ })
34
+
35
+ console = Console(theme=THEME, stderr=False)
36
+ err_console = Console(theme=THEME, stderr=True)
37
+
38
+
39
+ def is_json_mode(ctx: dict[str, Any]) -> bool:
40
+ return ctx.get("json_output", False) or not sys.stdout.isatty()
41
+
42
+
43
+ def print_json(data: Any) -> None:
44
+ """Print JSON to stdout (for pipe mode)."""
45
+ print(json.dumps(data, indent=2, default=str))
46
+
47
+
48
+ def print_error(message: str, ctx: dict[str, Any] | None = None) -> None:
49
+ if ctx and is_json_mode(ctx):
50
+ print_json({"error": message})
51
+ else:
52
+ err_console.print(f"[error]Error:[/error] {escape(message)}")
53
+
54
+
55
+ def print_success(message: str, ctx: dict[str, Any] | None = None) -> None:
56
+ if ctx and is_json_mode(ctx):
57
+ return
58
+ console.print(f"[success]{escape(message)}[/success]")
59
+
60
+
61
+ @contextmanager
62
+ def spinner(message: str = "Working...") -> Generator[None, None, None]:
63
+ """Show a spinner while work is in progress."""
64
+ with console.status(f"[info]{message}[/info]", spinner="dots"):
65
+ yield
66
+
67
+
68
+ def format_confidence(score: float) -> Text:
69
+ """Color-code a confidence score."""
70
+ text = f"{score:.1%}"
71
+ if score >= 0.8:
72
+ return Text(text, style="score.high")
73
+ elif score >= 0.5:
74
+ return Text(text, style="score.mid")
75
+ else:
76
+ return Text(text, style="score.low")
77
+
78
+
79
+ def format_timestamp(ts: str | float | int) -> str:
80
+ """Format a timestamp for display."""
81
+ try:
82
+ if isinstance(ts, (int, float)):
83
+ # Microsecond timestamps
84
+ if ts > 1e15:
85
+ ts = ts / 1e6
86
+ dt = datetime.fromtimestamp(ts, tz=timezone.utc)
87
+ else:
88
+ dt = datetime.fromisoformat(str(ts).replace("Z", "+00:00"))
89
+ return dt.strftime("%Y-%m-%d %H:%M")
90
+ except Exception:
91
+ return str(ts)[:16]
92
+
93
+
94
+ # ---------------------------------------------------------------------------
95
+ # High-level formatters
96
+ # ---------------------------------------------------------------------------
97
+
98
+
99
+ def print_health(data: dict[str, Any], ctx: dict[str, Any]) -> None:
100
+ """Render the /v1/auth/whoami response as a quick auth + reachability check."""
101
+ if is_json_mode(ctx):
102
+ print_json(data)
103
+ return
104
+ caller = data.get("caller", "")
105
+ tenant = data.get("tenant_id", "")
106
+ preset = data.get("deployment_preset", "")
107
+ token = data.get("token", {}) or {}
108
+ panel_text = "[green bold]OK[/green bold] — token verified, server reachable\n"
109
+ if caller:
110
+ panel_text += f"\nCaller: [bold]{escape(caller)}[/bold]"
111
+ if tenant:
112
+ panel_text += f"\nTenant: {escape(tenant)}"
113
+ if preset:
114
+ panel_text += f"\nDeployment: {escape(preset)}"
115
+ if token.get("jti"):
116
+ panel_text += f"\nToken jti: [dim]{escape(token['jti'])}[/dim]"
117
+ console.print(
118
+ Panel(panel_text, title="[header]CortexDB health[/header]", border_style="cyan")
119
+ )
120
+
121
+
122
+ def print_usage(data: dict[str, Any], ctx: dict[str, Any]) -> None:
123
+ """Render whoami + rate-limit + token-expiry response headers."""
124
+ if is_json_mode(ctx):
125
+ print_json(data)
126
+ return
127
+
128
+ caller = data.get("caller", "")
129
+ tenant = data.get("tenant_id", "")
130
+ caps = data.get("effective_capabilities", []) or []
131
+
132
+ table = Table(
133
+ title=f"[header]Identity & quota[/header] [dim]({escape(caller)})[/dim]",
134
+ border_style="cyan",
135
+ )
136
+ table.add_column("Field", style="bold")
137
+ table.add_column("Value")
138
+
139
+ if tenant:
140
+ table.add_row("Tenant", escape(tenant))
141
+ if data.get("deployment_preset"):
142
+ table.add_row("Deployment", escape(data["deployment_preset"]))
143
+
144
+ if data.get("X-RateLimit-Limit"):
145
+ table.add_row("Rate limit", escape(data["X-RateLimit-Limit"]))
146
+ if data.get("X-RateLimit-Reset"):
147
+ table.add_row("Resets at", escape(data["X-RateLimit-Reset"]))
148
+ if data.get("X-Cortex-Token-Expires-In"):
149
+ secs = int(data["X-Cortex-Token-Expires-In"])
150
+ days = secs // 86400
151
+ hrs = (secs % 86400) // 3600
152
+ table.add_row("Token expires in", f"{days}d {hrs}h")
153
+ if data.get("X-Cortex-Token-Expires-At"):
154
+ table.add_row("Token expires at", escape(data["X-Cortex-Token-Expires-At"]))
155
+
156
+ table.add_row("Capabilities", f"{len(caps)} granted")
157
+
158
+ console.print(table)
159
+ if caps:
160
+ console.print(
161
+ "[dim]" + " ".join(escape(c) for c in caps[:24]) + "[/dim]"
162
+ )
163
+
164
+
165
+ def print_remember(data: dict[str, Any], ctx: dict[str, Any]) -> None:
166
+ """Render the POST /v1/experience response."""
167
+ if is_json_mode(ctx):
168
+ print_json(data)
169
+ return
170
+ event_id = data.get("event_id") or data.get("id") or "unknown"
171
+ status = data.get("status", "captured")
172
+ scope = data.get("scope", "")
173
+ panel_text = f"[success]Stored[/success] [dim]({escape(status)})[/dim]"
174
+ panel_text += f"\n[dim]Event: {escape(event_id)}[/dim]"
175
+ if scope:
176
+ panel_text += f"\n[dim]Scope: {escape(scope)}[/dim]"
177
+ console.print(
178
+ Panel(panel_text, title="[header]Remember[/header]", border_style="green")
179
+ )
180
+
181
+
182
+ def print_recall(data: dict[str, Any], ctx: dict[str, Any]) -> None:
183
+ """Render a v1 StratifiedPack from /v1/recall."""
184
+ if is_json_mode(ctx):
185
+ print_json(data)
186
+ return
187
+ context = data.get("context_block") or data.get("context") or "(empty pack)"
188
+ pack_id = data.get("pack_id", "")
189
+ view = data.get("view", "")
190
+ prov = data.get("provenance", {}) or {}
191
+ trail = prov.get("trail") or []
192
+ latency = sum(p.get("elapsed_ms", 0) for p in trail if isinstance(p, dict))
193
+
194
+ header = Text()
195
+ if view:
196
+ header.append(f"View: {view} ", style="dim")
197
+ if latency:
198
+ header.append(f"Latency: {latency}ms ", style="dim")
199
+ if pack_id:
200
+ header.append(f"Pack: {pack_id}", style="dim")
201
+
202
+ console.print(
203
+ Panel(
204
+ f"{escape(str(context))}\n\n{header}",
205
+ title="[header]Memory recall[/header]",
206
+ border_style="cyan",
207
+ padding=(1, 2),
208
+ )
209
+ )
210
+
211
+
212
+ def print_search(data: dict[str, Any], ctx: dict[str, Any]) -> None:
213
+ """Render the granular events surface of a v1 recall pack."""
214
+ if is_json_mode(ctx):
215
+ print_json(data)
216
+ return
217
+
218
+ layers = data.get("layers", {}) or {}
219
+ events = layers.get("events") or data.get("events") or []
220
+ if isinstance(events, dict):
221
+ events = events.get("items", [])
222
+
223
+ if not events:
224
+ # Some servers return granular hits inline; fall back to context_block.
225
+ context = data.get("context_block") or ""
226
+ if context:
227
+ console.print(
228
+ Panel(escape(context), title="[header]Context[/header]", border_style="cyan")
229
+ )
230
+ else:
231
+ console.print("[dim]No results found.[/dim]")
232
+ return
233
+
234
+ table = Table(
235
+ title=f"[dim]{len(events)} matching events[/dim]",
236
+ border_style="blue",
237
+ show_lines=True,
238
+ )
239
+ table.add_column("#", style="dim", width=3)
240
+ table.add_column("Content", max_width=60)
241
+ table.add_column("Modality", style="cyan", width=12)
242
+ table.add_column("Observed at", style="dim", width=20)
243
+
244
+ for i, ev in enumerate(events, 1):
245
+ content = ev.get("content") or {}
246
+ text = ""
247
+ if isinstance(content, dict):
248
+ text = content.get("text") or content.get("summary") or ""
249
+ elif isinstance(content, str):
250
+ text = content
251
+ modality = ev.get("modality", "")
252
+ ts = (ev.get("context") or {}).get("observed_at") if isinstance(ev.get("context"), dict) else ev.get("observed_at", "")
253
+ table.add_row(str(i), escape(str(text)[:120]), escape(modality), format_timestamp(ts or ""))
254
+
255
+ console.print(table)
256
+
257
+
258
+ def print_episodes(data: dict[str, Any], ctx: dict[str, Any]) -> None:
259
+ """Render a v1 episodes response: {items: [Episode, …]}"""
260
+ if is_json_mode(ctx):
261
+ print_json(data)
262
+ return
263
+
264
+ episodes = data.get("items") or data.get("episodes") or []
265
+ if not episodes:
266
+ console.print("[dim]No episodes found.[/dim]")
267
+ return
268
+
269
+ table = Table(
270
+ title=f"[header]Episodes[/header] [dim]({len(episodes)})[/dim]",
271
+ border_style="blue",
272
+ )
273
+ table.add_column("ID", style="dim", max_width=16)
274
+ table.add_column("Summary", max_width=60)
275
+ table.add_column("Span events", style="cyan", justify="right", width=12)
276
+ table.add_column("Valid from", style="dim", width=20)
277
+
278
+ for ep in episodes:
279
+ eid = str(ep.get("episode_id") or ep.get("id", ""))[:16]
280
+ summary = ep.get("summary") or ep.get("title") or ""
281
+ spans = ep.get("event_count") or len(ep.get("event_ids") or [])
282
+ valid_from = ep.get("valid_from") or ep.get("observed_at", "")
283
+ table.add_row(
284
+ escape(eid), escape(str(summary)[:80]), str(spans), format_timestamp(valid_from)
285
+ )
286
+
287
+ console.print(table)
288
+
289
+
290
+ def print_entities(data: list[dict[str, Any]], ctx: dict[str, Any]) -> None:
291
+ """Render entity rollups derived from /v1/facts (subject, predicate count)."""
292
+ if is_json_mode(ctx):
293
+ print_json(data)
294
+ return
295
+
296
+ if not data:
297
+ console.print("[dim]No entities found.[/dim]")
298
+ return
299
+
300
+ table = Table(title="[header]Entities[/header]", border_style="blue")
301
+ table.add_column("Subject", style="bold", max_width=40)
302
+ table.add_column("Predicates", style="cyan", max_width=60)
303
+ table.add_column("Facts", justify="right")
304
+
305
+ for ent in data:
306
+ preds = ent.get("predicates") or []
307
+ preds_str = ", ".join(preds[:6])
308
+ if len(preds) > 6:
309
+ preds_str += f", +{len(preds) - 6}"
310
+ table.add_row(
311
+ escape(str(ent.get("subject") or ent.get("id", ""))),
312
+ escape(preds_str),
313
+ str(ent.get("fact_count", 0)),
314
+ )
315
+
316
+ console.print(table)
317
+
318
+
319
+ def print_entity_detail(data: dict[str, Any], ctx: dict[str, Any]) -> None:
320
+ """Render every fact about an entity (output of /v1/facts?subject=…)."""
321
+ if is_json_mode(ctx):
322
+ print_json(data)
323
+ return
324
+
325
+ subject = data.get("id") or data.get("subject", "")
326
+ facts = data.get("facts") or []
327
+ console.print(
328
+ Panel(
329
+ f"[bold]{escape(subject)}[/bold]\n[dim]{len(facts)} facts[/dim]",
330
+ title="[header]Entity[/header]",
331
+ border_style="cyan",
332
+ )
333
+ )
334
+
335
+ if not facts:
336
+ console.print("[dim]No facts recorded yet — the LLM extractor may not have run on related events.[/dim]")
337
+ return
338
+
339
+ table = Table(border_style="blue")
340
+ table.add_column("Predicate", style="magenta", max_width=24)
341
+ table.add_column("Object", style="bold")
342
+ table.add_column("Confidence", justify="right", width=10)
343
+ table.add_column("Valid from", style="dim", width=20)
344
+ for f in facts:
345
+ obj = f.get("object")
346
+ if isinstance(obj, dict):
347
+ obj_str = str(obj.get("value") or obj.get("id") or obj)
348
+ else:
349
+ obj_str = str(obj or "")
350
+ table.add_row(
351
+ escape(f.get("predicate", "")),
352
+ escape(obj_str),
353
+ f"{(f.get('confidence') or 0):.0%}",
354
+ format_timestamp(f.get("valid_from") or f.get("observed_at", "")),
355
+ )
356
+ console.print(table)
357
+
358
+
359
+ def print_forget(data: dict[str, Any], ctx: dict[str, Any]) -> None:
360
+ """Render the /v1/forget response."""
361
+ if is_json_mode(ctx):
362
+ print_json(data)
363
+ return
364
+ deleted = data.get("deleted_count") or data.get("forgotten") or 0
365
+ erasure_id = data.get("erasure_id") or data.get("audit_id", "")
366
+ cascade = data.get("cascade", "")
367
+ panel_text = f"Forgot [bold]{deleted}[/bold] item(s)"
368
+ if cascade:
369
+ panel_text += f" [dim](cascade: {escape(cascade)})[/dim]"
370
+ if erasure_id:
371
+ panel_text += f"\n[dim]Erasure id: {escape(erasure_id)}[/dim]"
372
+ console.print(
373
+ Panel(panel_text, title="[header]Forget[/header]", border_style="yellow")
374
+ )
375
+
376
+
377
+ def print_ontology(data: dict[str, Any], ctx: dict[str, Any]) -> None:
378
+ """Render /v1/admin/layers/stats (per-layer counts + lag)."""
379
+ if is_json_mode(ctx):
380
+ print_json(data)
381
+ return
382
+
383
+ layers = data.get("layers") or data
384
+ if not isinstance(layers, dict) or not layers:
385
+ console.print("[dim]No layer stats available on this tier.[/dim]")
386
+ return
387
+
388
+ table = Table(title="[header]Layer stats[/header]", border_style="cyan")
389
+ table.add_column("Layer", style="bold")
390
+ table.add_column("Count", justify="right")
391
+ table.add_column("Lag", style="dim", justify="right")
392
+ for name, info in layers.items():
393
+ if isinstance(info, dict):
394
+ count = info.get("count", info.get("total", ""))
395
+ lag = info.get("lag") or info.get("synthesis_lag", "")
396
+ table.add_row(escape(name), str(count), escape(str(lag)))
397
+ else:
398
+ table.add_row(escape(name), str(info), "")
399
+ console.print(table)
cortexdb_cli/state.py ADDED
@@ -0,0 +1,53 @@
1
+ """Persistent state for the CortexDB CLI.
2
+
3
+ We split secrets out of `~/.cortexdb/config.toml` (which is meant to be
4
+ human-editable) and into `~/.cortexdb/state.json`, written 0600 on POSIX.
5
+ State holds the PASETO bearer, actor, scope, and token expiry produced by
6
+ `POST /v1/auth/signup` — exactly the same shape the cortexdb-mcp 0.3.0
7
+ server persists. Keeping the format identical means a user who signed up
8
+ through one tool can copy state.json across to use the other.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import os
15
+ import stat
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ from cortexdb_cli.config import config_dir
20
+
21
+
22
+ def state_path() -> Path:
23
+ return config_dir() / "state.json"
24
+
25
+
26
+ def load_state() -> dict[str, Any]:
27
+ """Load persistent state. Returns {} if no state file exists."""
28
+ path = state_path()
29
+ if not path.exists():
30
+ return {}
31
+ try:
32
+ return json.loads(path.read_text(encoding="utf-8"))
33
+ except (OSError, json.JSONDecodeError):
34
+ return {}
35
+
36
+
37
+ def save_state(state: dict[str, Any]) -> None:
38
+ """Atomically write state and tighten permissions on POSIX."""
39
+ path = state_path()
40
+ tmp = path.with_suffix(".json.tmp")
41
+ tmp.write_text(json.dumps(state, indent=2, sort_keys=True), encoding="utf-8")
42
+ tmp.replace(path)
43
+ if os.name == "posix":
44
+ try:
45
+ os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
46
+ except OSError:
47
+ pass
48
+
49
+
50
+ def clear_state() -> None:
51
+ path = state_path()
52
+ if path.exists():
53
+ path.unlink()
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.4
2
+ Name: cortexdb-cli
3
+ Version: 0.2.0
4
+ Summary: Command-line interface for CortexDB — the long-term memory layer for AI.
5
+ Project-URL: Homepage, https://cortexdb.ai
6
+ Project-URL: Documentation, https://cortexdb.ai/docs
7
+ Project-URL: Repository, https://github.com/cortexdb/cortexdb
8
+ Project-URL: Issues, https://github.com/cortexdb/cortexdb/issues
9
+ Author-email: CortexDB Team <team@cortexdb.ai>
10
+ License-Expression: Apache-2.0
11
+ Keywords: agents,ai,cli,cortexdb,llm,memory
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Database
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: click>=8.1
25
+ Requires-Dist: httpx>=0.27
26
+ Requires-Dist: prompt-toolkit>=3.0
27
+ Requires-Dist: rich-click>=1.7
28
+ Requires-Dist: rich>=13.0
29
+ Requires-Dist: tomli-w>=1.0
30
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # cortexdb-cli
34
+
35
+ Command-line interface for [CortexDB](https://cortexdb.ai) — the long-term memory layer for AI systems.
36
+
37
+ Wraps the v1 HTTP API in a small, fast Click + Rich CLI. Anonymous signup
38
+ in one command, no email or card; works against the public SaaS or any
39
+ self-hosted CortexDB deployment.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install cortexdb-cli
45
+ ```
46
+
47
+ Requires Python 3.10+.
48
+
49
+ ## Quickstart
50
+
51
+ ```bash
52
+ # 1. One-time setup — anonymous signup, writes ~/.cortexdb/state.json
53
+ cortexdb init
54
+
55
+ # 2. Store a memory
56
+ cortexdb remember "Q3 revenue: $2.4M. We're on track for $10M ARR by year-end."
57
+
58
+ # 3. Recall it
59
+ cortexdb recall "Q3 revenue?"
60
+
61
+ # 4. Or just type — drops into a REPL
62
+ cortexdb
63
+ ```
64
+
65
+ The signup token has a 7-day TTL on the free tier. Re-run `cortexdb init`
66
+ to refresh, or pass `--api-key` + `--actor` to use a token from your IdP.
67
+
68
+ ## Commands
69
+
70
+ ```
71
+ cortexdb init anonymous signup; persist token + actor
72
+ cortexdb remember "..." store a memory (POST /v1/experience)
73
+ cortexdb recall "..." recall a stratified context pack
74
+ cortexdb search "..." granular event-level search
75
+ cortexdb forget --memory-id ... delete with audit
76
+ cortexdb episodes {list,get,delete} episode CRUD
77
+ cortexdb entities {list,get,link} entity rollups over the Facts layer
78
+ cortexdb admin {health,usage,layers} diagnostics
79
+ cortexdb import data.json bulk-load (JSON / JSONL / CSV / TXT)
80
+ cortexdb export -o backup.json export memories
81
+ cortexdb config {show,set} view / edit ~/.cortexdb/config.toml
82
+ cortexdb interactive REPL
83
+ ```
84
+
85
+ ## Configuration
86
+
87
+ Three layers, in precedence order:
88
+
89
+ 1. **CLI flags** — `--api-key`, `--endpoint`, `--actor`, `--scope`, `--profile`
90
+ 2. **Environment** — `CORTEXDB_API_KEY`, `CORTEXDB_URL`, `CORTEXDB_ACTOR`, `CORTEXDB_SCOPE`
91
+ 3. **Persisted state**:
92
+ - `~/.cortexdb/config.toml` — endpoint, profile names (human-editable)
93
+ - `~/.cortexdb/state.json` — token, actor, scope, expiry (managed by `init`, 0600 on POSIX)
94
+
95
+ The state.json format matches the cortexdb-mcp 0.3.0 server's, so you can
96
+ copy state across to use both tools from the same anonymous identity.
97
+
98
+ ## Pipe-friendly
99
+
100
+ Auto-detects when stdout isn't a TTY and emits JSON:
101
+
102
+ ```bash
103
+ cortexdb recall "Q3 revenue" | jq .context_block
104
+ cortexdb entities list | jq '.[].subject'
105
+ echo "remember this" | cortexdb remember -
106
+ ```
107
+
108
+ Force JSON mode any time with `--json`.
109
+
110
+ ## Auth notes
111
+
112
+ - The v1 API requires both `Authorization: Bearer <PASETO>` and `X-Cortex-Actor`.
113
+ The CLI stamps both on every request — you never need to pass them by hand.
114
+ - 401s show the specific error code (`TOKEN_EXPIRED`, `actor_mismatch`, …)
115
+ and the remediation: usually `cortexdb init`.
116
+ - 403s cite the missing capability and the policy tier that denied. If a
117
+ recall returns `diagnostics.read denied`, pass `--diagnostics none` —
118
+ free-tier tokens don't carry the `diagnostics.read` capability.
119
+
120
+ ## License
121
+
122
+ Apache-2.0
@@ -0,0 +1,31 @@
1
+ cortexdb_cli/__init__.py,sha256=ixhxihEV952X_SmT9JyodCc15IxaOntRFdA1XOFz72g,92
2
+ cortexdb_cli/client.py,sha256=t2i1jlIoNkppYaKtZMTkv99rwXI9v9iLQ_2BCX599Cw,2866
3
+ cortexdb_cli/config.py,sha256=JrHwQsfLAw56j0Yrafp_4HyW4TqIUVBEZuZFjxSlB0c,3609
4
+ cortexdb_cli/errors.py,sha256=xwxAWYY7KtNa-e7dyLQECnsKcciVcKC41CXFFF_-0VU,3924
5
+ cortexdb_cli/main.py,sha256=RLqcyQzDSTk-IlE2jJ9Camf3FrqH2GZb-TAMRItwB80,5272
6
+ cortexdb_cli/output.py,sha256=X2XosVQXEHPSQy0UnEzJyCDiOI9h3TRMneLlgEaEFQM,14014
7
+ cortexdb_cli/state.py,sha256=yxy1ODTdBkRUKnTz8vBEvojuH4ieRbME4ccVMj--bwk,1529
8
+ cortexdb_cli/commands/__init__.py,sha256=TeF4ieMQkbgBr9Fco9VAiIZvKQ4vdg4yhkz4fvwfToc,37
9
+ cortexdb_cli/commands/admin.py,sha256=1fyMVujNTBzBkWthgj1GXRsWXGM2FyBv_PfvZUMBfFQ,2516
10
+ cortexdb_cli/commands/answer.py,sha256=m9Tn2XAdXpwgYQDEaBVex3PAyGO5NisVAhU83dzoDVo,2904
11
+ cortexdb_cli/commands/auth.py,sha256=0kbOZenps3ydPM_HIisZNXFoQhNuG4hyBNnvF5UYHt8,4521
12
+ cortexdb_cli/commands/beliefs.py,sha256=55zNUMfwzqRWlkGHuv5xJFN_QEeLMhqXK2qf5zl9gCc,4043
13
+ cortexdb_cli/commands/config_cmd.py,sha256=9XwPJLWubvc6QY8EnVJd8mhQFSITnhQYlclJaQqr0VU,1519
14
+ cortexdb_cli/commands/entities.py,sha256=8jQwL14yzwF2j7_-447WTlFTFsNxZ30MWH4na1K2CdE,6067
15
+ cortexdb_cli/commands/episodes.py,sha256=oeXSSgnt_FPqgoI2nTHdYe56iwo6ydzR2Bp1_K25CV0,4135
16
+ cortexdb_cli/commands/experience.py,sha256=13u8907HrQz8UepD9agv22UOMzOdV6Hq654qswdsgOQ,7591
17
+ cortexdb_cli/commands/export_cmd.py,sha256=v5nnApGz6yJRhnTh2CCB8siYI1xJfn9dOaeSgZb1Zdo,1986
18
+ cortexdb_cli/commands/facts.py,sha256=2eFLum7kIG3QiS5_M_5yrv8puxwXZ-bE8dMhtks9Fco,5405
19
+ cortexdb_cli/commands/forget.py,sha256=tEhXHlpM6mXIxe0TJrwAnfNNBvDXm1dNgVXwKuNHpaM,2948
20
+ cortexdb_cli/commands/import_cmd.py,sha256=SEsxTStwS8LF5ebehCZtvyYGAPEAnq5rqFPTrem3oCY,6458
21
+ cortexdb_cli/commands/init.py,sha256=FgFwPell0x8-rA1ECKiT0cBcDWoIhCVS6TsRp-_JH84,3035
22
+ cortexdb_cli/commands/interactive.py,sha256=L0qUCMfm1jzPrPKvKXqu9Tiz9qvcrRCsICs7OAvyZ3I,9518
23
+ cortexdb_cli/commands/policy.py,sha256=IT2o-OogGHfcBCyMM3ht_OCpmG7d2ryHsJpFxK-l6R4,3362
24
+ cortexdb_cli/commands/recall.py,sha256=nmFVQyojaI6xHVWh3rIF5nKo8_chYc7BFlp_zu4JPXk,2680
25
+ cortexdb_cli/commands/scopes.py,sha256=6cNGt9mHJe8M10QkekifhJ86TVuzWIOxHzxUrDUQPhY,3052
26
+ cortexdb_cli/commands/search.py,sha256=aRAd8161ItytQJvYaG7K1an003GA8yDbW4AwOhfRkIE,1957
27
+ cortexdb_cli/commands/understanding.py,sha256=6YJEmRPGkP6jqn7RQgp6zkbbvYZis2eHDbQ190Y0UXM,5009
28
+ cortexdb_cli-0.2.0.dist-info/METADATA,sha256=lnIlhxdPYCQVaCAn-osZ3BXuLC2vyP0u3SZ29mw3R0o,4429
29
+ cortexdb_cli-0.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
30
+ cortexdb_cli-0.2.0.dist-info/entry_points.txt,sha256=h3sEbdqqvtv8LBbRLUgybYPo9N2lpU85fQUSh5ToEvs,51
31
+ cortexdb_cli-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cortexdb = cortexdb_cli.main:cli