minima-cli 0.4.9__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.
- minima/__init__.py +5 -0
- minima/api/__init__.py +1 -0
- minima/api/auth.py +39 -0
- minima/api/errors.py +40 -0
- minima/api/routers/__init__.py +1 -0
- minima/api/routers/calibration.py +50 -0
- minima/api/routers/feedback.py +279 -0
- minima/api/routers/health.py +50 -0
- minima/api/routers/models.py +42 -0
- minima/api/routers/recommend.py +66 -0
- minima/api/routers/savings.py +55 -0
- minima/api/routers/strategies.py +33 -0
- minima/catalog/__init__.py +1 -0
- minima/catalog/data/capability_priors.json +210 -0
- minima/catalog/data/model_aliases.json +12 -0
- minima/catalog/merge.py +69 -0
- minima/catalog/refresh.py +54 -0
- minima/catalog/sources/__init__.py +1 -0
- minima/catalog/sources/litellm.py +19 -0
- minima/catalog/sources/openrouter.py +25 -0
- minima/catalog/store.py +86 -0
- minima/config.py +288 -0
- minima/deps.py +35 -0
- minima/llm/__init__.py +1 -0
- minima/llm/anthropic.py +106 -0
- minima/llm/base.py +196 -0
- minima/llm/gemini.py +124 -0
- minima/llm/registry.py +54 -0
- minima/logging.py +28 -0
- minima/main.py +109 -0
- minima/memory/__init__.py +1 -0
- minima/memory/adapter.py +572 -0
- minima/memory/keys.py +83 -0
- minima/memory/records.py +190 -0
- minima/memory/threadpool.py +41 -0
- minima/metrics/__init__.py +1 -0
- minima/metrics/calibration.py +415 -0
- minima/metrics/report.py +116 -0
- minima/metrics/savings.py +98 -0
- minima/recommender/__init__.py +1 -0
- minima/recommender/_pg_pool.py +38 -0
- minima/recommender/_redis_client.py +32 -0
- minima/recommender/aggregate.py +157 -0
- minima/recommender/classify.py +165 -0
- minima/recommender/decisionlog.py +505 -0
- minima/recommender/durablerefs.py +312 -0
- minima/recommender/engine.py +997 -0
- minima/recommender/escalation.py +83 -0
- minima/recommender/propensity.py +189 -0
- minima/recommender/recstore.py +368 -0
- minima/recommender/score.py +318 -0
- minima/recommender/types.py +166 -0
- minima/schemas/__init__.py +1 -0
- minima/schemas/common.py +73 -0
- minima/schemas/feedback.py +34 -0
- minima/schemas/models_catalog.py +36 -0
- minima/schemas/recommend.py +104 -0
- minima/schemas/savings.py +39 -0
- minima/schemas/strategies.py +57 -0
- minima/schemas/workflow.py +43 -0
- minima/seeding/__init__.py +1 -0
- minima/seeding/items.py +42 -0
- minima/seeding/llmrouterbench.py +232 -0
- minima/seeding/routerbench.py +141 -0
- minima/seeding/run_seed.py +56 -0
- minima/seeding/synthetic.py +70 -0
- minima/tenancy/__init__.py +8 -0
- minima/tenancy/context.py +37 -0
- minima/tenancy/passthrough.py +110 -0
- minima/version.py +3 -0
- minima_cli-0.4.9.dist-info/METADATA +275 -0
- minima_cli-0.4.9.dist-info/RECORD +161 -0
- minima_cli-0.4.9.dist-info/WHEEL +4 -0
- minima_cli-0.4.9.dist-info/entry_points.txt +5 -0
- minima_cli-0.4.9.dist-info/licenses/LICENSE +295 -0
- minima_client/__init__.py +19 -0
- minima_client/autocapture.py +101 -0
- minima_client/client.py +301 -0
- minima_client/errors.py +23 -0
- minima_harness/LICENSE_PI +32 -0
- minima_harness/__init__.py +16 -0
- minima_harness/agent/__init__.py +72 -0
- minima_harness/agent/agent.py +276 -0
- minima_harness/agent/events.py +124 -0
- minima_harness/agent/loop.py +311 -0
- minima_harness/agent/state.py +79 -0
- minima_harness/agent/tools.py +97 -0
- minima_harness/ai/__init__.py +66 -0
- minima_harness/ai/compat.py +71 -0
- minima_harness/ai/errors.py +96 -0
- minima_harness/ai/events.py +117 -0
- minima_harness/ai/openrouter_catalog.py +153 -0
- minima_harness/ai/provider_catalog.py +299 -0
- minima_harness/ai/provider_quirks.py +37 -0
- minima_harness/ai/providers/__init__.py +75 -0
- minima_harness/ai/providers/_common.py +48 -0
- minima_harness/ai/providers/anthropic.py +290 -0
- minima_harness/ai/providers/base.py +65 -0
- minima_harness/ai/providers/faux.py +173 -0
- minima_harness/ai/providers/google.py +221 -0
- minima_harness/ai/providers/openai_compat.py +278 -0
- minima_harness/ai/registry.py +184 -0
- minima_harness/ai/stream.py +82 -0
- minima_harness/ai/tools.py +51 -0
- minima_harness/ai/types.py +204 -0
- minima_harness/ai/usage.py +41 -0
- minima_harness/minima/__init__.py +40 -0
- minima_harness/minima/cache.py +102 -0
- minima_harness/minima/config.py +85 -0
- minima_harness/minima/goals.py +226 -0
- minima_harness/minima/judge.py +144 -0
- minima_harness/minima/mapping.py +147 -0
- minima_harness/minima/meter.py +143 -0
- minima_harness/minima/router.py +220 -0
- minima_harness/minima/runtime.py +544 -0
- minima_harness/minima/signals.py +195 -0
- minima_harness/session/__init__.py +14 -0
- minima_harness/session/format.py +35 -0
- minima_harness/session/store.py +236 -0
- minima_harness/tasks/__init__.py +17 -0
- minima_harness/tasks/task_set.py +78 -0
- minima_harness/tools/__init__.py +7 -0
- minima_harness/tools/_io.py +34 -0
- minima_harness/tools/bash.py +70 -0
- minima_harness/tools/builtin.py +23 -0
- minima_harness/tools/edit.py +50 -0
- minima_harness/tools/find.py +38 -0
- minima_harness/tools/grep.py +73 -0
- minima_harness/tools/ls.py +35 -0
- minima_harness/tools/read.py +38 -0
- minima_harness/tools/tasks.py +75 -0
- minima_harness/tools/write.py +36 -0
- minima_harness/tui/__init__.py +3 -0
- minima_harness/tui/analytics.py +111 -0
- minima_harness/tui/app.py +1927 -0
- minima_harness/tui/bridge.py +103 -0
- minima_harness/tui/cli.py +227 -0
- minima_harness/tui/clipboard.py +60 -0
- minima_harness/tui/commands.py +49 -0
- minima_harness/tui/compaction.py +17 -0
- minima_harness/tui/config_cli.py +141 -0
- minima_harness/tui/config_store.py +237 -0
- minima_harness/tui/context.py +93 -0
- minima_harness/tui/customize.py +95 -0
- minima_harness/tui/diff.py +53 -0
- minima_harness/tui/editor.py +43 -0
- minima_harness/tui/extensions.py +84 -0
- minima_harness/tui/extra_models.py +52 -0
- minima_harness/tui/history.py +71 -0
- minima_harness/tui/mubit.py +295 -0
- minima_harness/tui/overlays.py +593 -0
- minima_harness/tui/packages.py +59 -0
- minima_harness/tui/run_modes.py +66 -0
- minima_harness/tui/theme.py +77 -0
- minima_harness/tui/welcome.py +83 -0
- minima_harness/tui/widgets/__init__.py +3 -0
- minima_harness/tui/widgets/banner.py +38 -0
- minima_harness/tui/widgets/editor.py +83 -0
- minima_harness/tui/widgets/footer.py +73 -0
- minima_harness/tui/widgets/messages.py +151 -0
- minima_harness/tui/widgets/status.py +57 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"""Bookkeeping for the durable (cluster, model) outcome records' Dereference ids.
|
|
2
|
+
|
|
3
|
+
Minima upserts exactly one durable outcome record per (lane, cluster, model) in Mubit
|
|
4
|
+
(``minima:om:{cluster}:{model_id}``). ANN recall usually surfaces it — but embedding
|
|
5
|
+
noise can push the single most-informative record out of the top-k. This store remembers
|
|
6
|
+
each durable record's stable entry id so the engine can Dereference it directly (exact
|
|
7
|
+
re-read) alongside recall, guaranteeing the highest-signal evidence is present.
|
|
8
|
+
|
|
9
|
+
Rows are written from two sources: feedback (the remember() record_id — upserts keep it
|
|
10
|
+
stable) and recall hits whose record matches the current cluster. Seeds are excluded
|
|
11
|
+
(they are per-row batch inserts, not the durable upsert).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import sqlite3
|
|
17
|
+
import time
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from threading import Lock
|
|
20
|
+
from typing import Protocol, runtime_checkable
|
|
21
|
+
|
|
22
|
+
from minima.config import Settings
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(slots=True)
|
|
26
|
+
class DurableRef:
|
|
27
|
+
model_id: str
|
|
28
|
+
entry_id: str
|
|
29
|
+
reference_id: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@runtime_checkable
|
|
33
|
+
class DurableRefs(Protocol):
|
|
34
|
+
def upsert(
|
|
35
|
+
self, lane: str, cluster: str, model_id: str, entry_id: str, reference_id: str
|
|
36
|
+
) -> None: ...
|
|
37
|
+
|
|
38
|
+
def refs(self, lane: str, cluster: str, limit: int = 8) -> list[DurableRef]: ...
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class MemoryDurableRefs:
|
|
42
|
+
"""In-process store (lost on restart — recall hits repopulate it organically)."""
|
|
43
|
+
|
|
44
|
+
def __init__(self) -> None:
|
|
45
|
+
self._data: dict[tuple[str, str, str], dict[str, DurableRef]] = {}
|
|
46
|
+
self._lock = Lock()
|
|
47
|
+
|
|
48
|
+
def upsert(
|
|
49
|
+
self,
|
|
50
|
+
lane: str,
|
|
51
|
+
cluster: str,
|
|
52
|
+
model_id: str,
|
|
53
|
+
entry_id: str,
|
|
54
|
+
reference_id: str,
|
|
55
|
+
org_id: str = "default",
|
|
56
|
+
) -> None:
|
|
57
|
+
if not entry_id and not reference_id:
|
|
58
|
+
return
|
|
59
|
+
with self._lock:
|
|
60
|
+
bucket = self._data.setdefault((org_id, lane, cluster), {})
|
|
61
|
+
bucket[model_id] = DurableRef(
|
|
62
|
+
model_id=model_id, entry_id=entry_id, reference_id=reference_id or entry_id
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def refs(
|
|
66
|
+
self, lane: str, cluster: str, limit: int = 8, org_id: str = "default"
|
|
67
|
+
) -> list[DurableRef]:
|
|
68
|
+
with self._lock:
|
|
69
|
+
bucket = self._data.get((org_id, lane, cluster), {})
|
|
70
|
+
return list(bucket.values())[: max(0, limit)]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SqliteDurableRefs:
|
|
74
|
+
"""Durable store backed by SQLite (stdlib; shares the state DB file)."""
|
|
75
|
+
|
|
76
|
+
def __init__(self, path: str):
|
|
77
|
+
self._conn = sqlite3.connect(path, check_same_thread=False)
|
|
78
|
+
self._lock = Lock()
|
|
79
|
+
with self._conn:
|
|
80
|
+
self._conn.execute(
|
|
81
|
+
"""
|
|
82
|
+
CREATE TABLE IF NOT EXISTS durable_refs (
|
|
83
|
+
org_id TEXT NOT NULL DEFAULT 'default',
|
|
84
|
+
lane TEXT NOT NULL,
|
|
85
|
+
cluster TEXT NOT NULL,
|
|
86
|
+
model_id TEXT NOT NULL,
|
|
87
|
+
entry_id TEXT NOT NULL,
|
|
88
|
+
reference_id TEXT NOT NULL,
|
|
89
|
+
updated_at REAL NOT NULL
|
|
90
|
+
)
|
|
91
|
+
"""
|
|
92
|
+
)
|
|
93
|
+
self._conn.execute(
|
|
94
|
+
"CREATE UNIQUE INDEX IF NOT EXISTS ux_durable_refs "
|
|
95
|
+
"ON durable_refs(org_id, lane, cluster, model_id)"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def upsert(
|
|
99
|
+
self,
|
|
100
|
+
lane: str,
|
|
101
|
+
cluster: str,
|
|
102
|
+
model_id: str,
|
|
103
|
+
entry_id: str,
|
|
104
|
+
reference_id: str,
|
|
105
|
+
org_id: str = "default",
|
|
106
|
+
) -> None:
|
|
107
|
+
if not entry_id and not reference_id:
|
|
108
|
+
return
|
|
109
|
+
with self._lock, self._conn:
|
|
110
|
+
self._conn.execute(
|
|
111
|
+
"""
|
|
112
|
+
INSERT INTO durable_refs
|
|
113
|
+
(org_id, lane, cluster, model_id, entry_id, reference_id, updated_at)
|
|
114
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
115
|
+
ON CONFLICT(org_id, lane, cluster, model_id) DO UPDATE SET
|
|
116
|
+
entry_id = excluded.entry_id,
|
|
117
|
+
reference_id = excluded.reference_id,
|
|
118
|
+
updated_at = excluded.updated_at
|
|
119
|
+
""",
|
|
120
|
+
(
|
|
121
|
+
org_id,
|
|
122
|
+
lane,
|
|
123
|
+
cluster,
|
|
124
|
+
model_id,
|
|
125
|
+
entry_id,
|
|
126
|
+
reference_id or entry_id,
|
|
127
|
+
time.time(),
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def refs(
|
|
132
|
+
self, lane: str, cluster: str, limit: int = 8, org_id: str = "default"
|
|
133
|
+
) -> list[DurableRef]:
|
|
134
|
+
with self._lock:
|
|
135
|
+
rows = self._conn.execute(
|
|
136
|
+
"SELECT model_id, entry_id, reference_id FROM durable_refs "
|
|
137
|
+
"WHERE org_id = ? AND lane = ? AND cluster = ? "
|
|
138
|
+
"ORDER BY updated_at DESC LIMIT ?",
|
|
139
|
+
(org_id, lane, cluster, max(0, limit)),
|
|
140
|
+
).fetchall()
|
|
141
|
+
return [
|
|
142
|
+
DurableRef(model_id=str(m), entry_id=str(e), reference_id=str(r)) for m, e, r in rows
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
def close(self) -> None:
|
|
146
|
+
with self._lock:
|
|
147
|
+
self._conn.close()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class OrgScopedDurableRefs:
|
|
151
|
+
"""Binds a shared backend to one org, presenting the ``DurableRefs`` Protocol."""
|
|
152
|
+
|
|
153
|
+
def __init__(self, backend: DurableRefs, org_id: str):
|
|
154
|
+
self._backend = backend
|
|
155
|
+
self._org_id = org_id
|
|
156
|
+
|
|
157
|
+
def upsert(
|
|
158
|
+
self, lane: str, cluster: str, model_id: str, entry_id: str, reference_id: str
|
|
159
|
+
) -> None:
|
|
160
|
+
self._backend.upsert(lane, cluster, model_id, entry_id, reference_id, self._org_id) # type: ignore[call-arg]
|
|
161
|
+
|
|
162
|
+
def refs(self, lane: str, cluster: str, limit: int = 8) -> list[DurableRef]:
|
|
163
|
+
return self._backend.refs(lane, cluster, limit, self._org_id) # type: ignore[call-arg]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class PostgresDurableRefs:
|
|
167
|
+
"""Durable refs store backed by PostgreSQL."""
|
|
168
|
+
|
|
169
|
+
def __init__(self, database_url: str):
|
|
170
|
+
from minima.recommender._pg_pool import cursor as _cursor
|
|
171
|
+
|
|
172
|
+
self._url = database_url
|
|
173
|
+
self._cursor = _cursor
|
|
174
|
+
with self._cursor(self._url) as cur:
|
|
175
|
+
cur.execute(
|
|
176
|
+
"""
|
|
177
|
+
CREATE TABLE IF NOT EXISTS durable_refs (
|
|
178
|
+
org_id TEXT NOT NULL DEFAULT 'default',
|
|
179
|
+
lane TEXT NOT NULL,
|
|
180
|
+
cluster TEXT NOT NULL,
|
|
181
|
+
model_id TEXT NOT NULL,
|
|
182
|
+
entry_id TEXT NOT NULL,
|
|
183
|
+
reference_id TEXT NOT NULL,
|
|
184
|
+
updated_at DOUBLE PRECISION NOT NULL,
|
|
185
|
+
UNIQUE(org_id, lane, cluster, model_id)
|
|
186
|
+
)
|
|
187
|
+
"""
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def upsert(
|
|
191
|
+
self,
|
|
192
|
+
lane: str,
|
|
193
|
+
cluster: str,
|
|
194
|
+
model_id: str,
|
|
195
|
+
entry_id: str,
|
|
196
|
+
reference_id: str,
|
|
197
|
+
org_id: str = "default",
|
|
198
|
+
) -> None:
|
|
199
|
+
if not entry_id and not reference_id:
|
|
200
|
+
return
|
|
201
|
+
with self._cursor(self._url) as cur:
|
|
202
|
+
cur.execute(
|
|
203
|
+
"""
|
|
204
|
+
INSERT INTO durable_refs
|
|
205
|
+
(org_id, lane, cluster, model_id, entry_id, reference_id, updated_at)
|
|
206
|
+
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
|
207
|
+
ON CONFLICT (org_id, lane, cluster, model_id) DO UPDATE SET
|
|
208
|
+
entry_id = EXCLUDED.entry_id,
|
|
209
|
+
reference_id = EXCLUDED.reference_id,
|
|
210
|
+
updated_at = EXCLUDED.updated_at
|
|
211
|
+
""",
|
|
212
|
+
(
|
|
213
|
+
org_id,
|
|
214
|
+
lane,
|
|
215
|
+
cluster,
|
|
216
|
+
model_id,
|
|
217
|
+
entry_id,
|
|
218
|
+
reference_id or entry_id,
|
|
219
|
+
time.time(),
|
|
220
|
+
),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
def refs(
|
|
224
|
+
self, lane: str, cluster: str, limit: int = 8, org_id: str = "default"
|
|
225
|
+
) -> list[DurableRef]:
|
|
226
|
+
with self._cursor(self._url) as cur:
|
|
227
|
+
cur.execute(
|
|
228
|
+
"SELECT model_id, entry_id, reference_id FROM durable_refs"
|
|
229
|
+
" WHERE org_id = %s AND lane = %s AND cluster = %s"
|
|
230
|
+
" ORDER BY updated_at DESC LIMIT %s",
|
|
231
|
+
(org_id, lane, cluster, max(0, limit)),
|
|
232
|
+
)
|
|
233
|
+
rows = cur.fetchall()
|
|
234
|
+
return [
|
|
235
|
+
DurableRef(model_id=str(m), entry_id=str(e), reference_id=str(r)) for m, e, r in rows
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class RedisDurableRefs:
|
|
240
|
+
"""Durable refs store backed by Redis (Cloud Memorystore).
|
|
241
|
+
|
|
242
|
+
Each (org_id, lane, cluster) bucket is a Redis hash keyed by model_id, with
|
|
243
|
+
the value being a JSON-encoded {entry_id, reference_id}. No TTL — refs are
|
|
244
|
+
long-lived and updated in-place as new outcomes arrive.
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
def __init__(self, redis_url: str):
|
|
248
|
+
from minima.recommender._redis_client import get_client
|
|
249
|
+
|
|
250
|
+
self._r = get_client(redis_url)
|
|
251
|
+
|
|
252
|
+
def _key(self, org_id: str, lane: str, cluster: str) -> str:
|
|
253
|
+
return f"drefs:{org_id}:{lane}:{cluster}"
|
|
254
|
+
|
|
255
|
+
def upsert(
|
|
256
|
+
self,
|
|
257
|
+
lane: str,
|
|
258
|
+
cluster: str,
|
|
259
|
+
model_id: str,
|
|
260
|
+
entry_id: str,
|
|
261
|
+
reference_id: str,
|
|
262
|
+
org_id: str = "default",
|
|
263
|
+
) -> None:
|
|
264
|
+
import json
|
|
265
|
+
|
|
266
|
+
if not entry_id and not reference_id:
|
|
267
|
+
return
|
|
268
|
+
self._r.hset(
|
|
269
|
+
self._key(org_id, lane, cluster),
|
|
270
|
+
model_id,
|
|
271
|
+
json.dumps({"entry_id": entry_id, "reference_id": reference_id or entry_id}),
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def refs(
|
|
275
|
+
self, lane: str, cluster: str, limit: int = 8, org_id: str = "default"
|
|
276
|
+
) -> list[DurableRef]:
|
|
277
|
+
import json
|
|
278
|
+
|
|
279
|
+
raw = self._r.hgetall(self._key(org_id, lane, cluster))
|
|
280
|
+
from minima.recommender._redis_client import decode
|
|
281
|
+
|
|
282
|
+
out: list[DurableRef] = []
|
|
283
|
+
for model_id, value in raw.items():
|
|
284
|
+
d = json.loads(value)
|
|
285
|
+
out.append(
|
|
286
|
+
DurableRef(
|
|
287
|
+
model_id=decode(model_id),
|
|
288
|
+
entry_id=d["entry_id"],
|
|
289
|
+
reference_id=d["reference_id"],
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
return out[: max(0, limit)]
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def build_durable_refs(settings: Settings) -> DurableRefs:
|
|
296
|
+
backend = (
|
|
297
|
+
settings.minima_recstore_backend.strip().lower()
|
|
298
|
+
or settings.minima_recommendation_store.strip().lower()
|
|
299
|
+
)
|
|
300
|
+
if backend == "redis":
|
|
301
|
+
if not settings.minima_redis_url:
|
|
302
|
+
raise RuntimeError("MINIMA_REDIS_URL is required when MINIMA_RECSTORE_BACKEND=redis")
|
|
303
|
+
return RedisDurableRefs(settings.minima_redis_url)
|
|
304
|
+
if backend in ("cloudsql", "postgres", "postgresql"):
|
|
305
|
+
if not settings.minima_database_url:
|
|
306
|
+
raise RuntimeError(
|
|
307
|
+
"MINIMA_DATABASE_URL is required when MINIMA_RECOMMENDATION_STORE=cloudsql"
|
|
308
|
+
)
|
|
309
|
+
return PostgresDurableRefs(settings.minima_database_url)
|
|
310
|
+
if backend == "sqlite":
|
|
311
|
+
return SqliteDurableRefs(settings.minima_sqlite_path)
|
|
312
|
+
return MemoryDurableRefs()
|