@mafdet/cli 0.4.1 → 0.4.2
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/CHANGELOG.md +34 -0
- package/README.md +61 -0
- package/README.zh-CN.md +52 -0
- package/dist/agent/loop.d.ts +14 -0
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +16 -3
- package/dist/agent/session.d.ts +5 -0
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +1 -1
- package/dist/agent/tools/read-only.d.ts.map +1 -1
- package/dist/agent/tools/read-only.js +6 -0
- package/dist/api/account.d.ts +43 -0
- package/dist/api/account.d.ts.map +1 -1
- package/dist/api/account.js +40 -0
- package/dist/commands/sessions.d.ts +5 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +379 -0
- package/dist/config/paths.d.ts +7 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +24 -0
- package/dist/filesystem/protected-dirs.d.ts +26 -0
- package/dist/filesystem/protected-dirs.d.ts.map +1 -0
- package/dist/filesystem/protected-dirs.js +78 -0
- package/dist/filesystem/workspace.d.ts +12 -1
- package/dist/filesystem/workspace.d.ts.map +1 -1
- package/dist/filesystem/workspace.js +24 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/security/redact.d.ts +26 -3
- package/dist/security/redact.d.ts.map +1 -1
- package/dist/security/redact.js +48 -3
- package/dist/sessions/index-file.d.ts +38 -0
- package/dist/sessions/index-file.d.ts.map +1 -0
- package/dist/sessions/index-file.js +174 -0
- package/dist/sessions/lock.d.ts +39 -0
- package/dist/sessions/lock.d.ts.map +1 -0
- package/dist/sessions/lock.js +134 -0
- package/dist/sessions/open.d.ts +45 -0
- package/dist/sessions/open.d.ts.map +1 -0
- package/dist/sessions/open.js +96 -0
- package/dist/sessions/policy.d.ts +32 -0
- package/dist/sessions/policy.d.ts.map +1 -0
- package/dist/sessions/policy.js +57 -0
- package/dist/sessions/reconcile.d.ts +49 -0
- package/dist/sessions/reconcile.d.ts.map +1 -0
- package/dist/sessions/reconcile.js +115 -0
- package/dist/sessions/recorder.d.ts +42 -0
- package/dist/sessions/recorder.d.ts.map +1 -0
- package/dist/sessions/recorder.js +147 -0
- package/dist/sessions/resume.d.ts +67 -0
- package/dist/sessions/resume.d.ts.map +1 -0
- package/dist/sessions/resume.js +100 -0
- package/dist/sessions/store.d.ts +141 -0
- package/dist/sessions/store.d.ts.map +1 -0
- package/dist/sessions/store.js +272 -0
- package/dist/sessions/usage.d.ts +35 -0
- package/dist/sessions/usage.d.ts.map +1 -0
- package/dist/sessions/usage.js +157 -0
- package/dist/tui/agent-surface.d.ts +3 -0
- package/dist/tui/agent-surface.d.ts.map +1 -1
- package/dist/tui/agent-surface.js +16 -1
- package/dist/tui/app.d.ts.map +1 -1
- package/dist/tui/app.js +18 -1
- package/dist/tui/route.d.ts.map +1 -1
- package/dist/tui/route.js +19 -2
- package/dist/tui/session-centre.d.ts +15 -0
- package/dist/tui/session-centre.d.ts.map +1 -0
- package/dist/tui/session-centre.js +59 -0
- package/dist/tui/start-agent.d.ts +9 -0
- package/dist/tui/start-agent.d.ts.map +1 -1
- package/dist/tui/start-agent.js +122 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,40 @@ The version is the contract for the JSON output shapes and the exit codes.
|
|
|
6
6
|
Being 0.x, semver still permits a break in a minor bump; the intent is not to
|
|
7
7
|
use that latitude, and the promise becomes binding at 1.0.0.
|
|
8
8
|
|
|
9
|
+
## 0.4.2 - 2026-08-11
|
|
10
|
+
|
|
11
|
+
Conversations are now saved on this computer, and a session's cost can be
|
|
12
|
+
reconciled against the billing ledger.
|
|
13
|
+
|
|
14
|
+
`mafdet sessions list|show|usage|delete` browses what is stored locally. None
|
|
15
|
+
of it calls a model, so reading your own history is never charged. Recording
|
|
16
|
+
is on by default for interactive sessions and off wherever a machine is
|
|
17
|
+
reading the output; `--no-history` writes nothing at all.
|
|
18
|
+
|
|
19
|
+
The transcript is plain text and stays on this machine - it is not uploaded,
|
|
20
|
+
and Mafdet holds no copy. That is a statement about the archive, not about the
|
|
21
|
+
model: the messages you send are still sent to the API to be answered and
|
|
22
|
+
still appear in your usage records. The README says where the files live on
|
|
23
|
+
each platform, and that deleting one is an ordinary file delete rather than a
|
|
24
|
+
secure erase.
|
|
25
|
+
|
|
26
|
+
`mafdet sessions usage <id> --refresh` asks the billing ledger what the
|
|
27
|
+
requests actually cost and replaces the local estimate with the settled
|
|
28
|
+
figure. It sends the request IDs already in the transcript and nothing else -
|
|
29
|
+
no messages, no title, no workspace, no session ID. Requests paid for by a
|
|
30
|
+
different API key are left alone and reported rather than guessed at, and a
|
|
31
|
+
request the ledger has not settled stays `pending` rather than being shown as
|
|
32
|
+
zero.
|
|
33
|
+
|
|
34
|
+
The agent cannot read the CLI's own directories, even when you run `mafdet`
|
|
35
|
+
from your home directory and the session store is technically inside the
|
|
36
|
+
workspace.
|
|
37
|
+
|
|
38
|
+
Fixed on the way: the value recorded to attribute usage to a key was the
|
|
39
|
+
display fingerprint, which renders every live key identically - so a session
|
|
40
|
+
that used two keys reported them as one. It is now a digest that actually
|
|
41
|
+
differs per key, and still cannot be turned back into a key.
|
|
42
|
+
|
|
9
43
|
## 0.4.1 - 2026-08-07
|
|
10
44
|
|
|
11
45
|
Fixes Ctrl+C in the interactive session, which did nothing while a model
|
package/README.md
CHANGED
|
@@ -88,6 +88,8 @@ prompt as an argument, or use `--input <file>`.
|
|
|
88
88
|
| `mafdet embed [text\|<file>] --model <id> [--output <file>]` | Text to vector |
|
|
89
89
|
| `mafdet speech [text\|<file>] --model <id> --output <file> --voice <name>` | Text to an audio file |
|
|
90
90
|
| `mafdet account balance\|usage\|subscription` | Wallet, spend and plan (needs the `account:read` scope) |
|
|
91
|
+
| `mafdet sessions list\|show\|usage\|delete` | Conversations saved on this computer (never calls a model) |
|
|
92
|
+
| `mafdet sessions usage <id> --refresh` | Replace the local estimate with the billing ledger's figure |
|
|
91
93
|
| `mafdet config list` | The resolved settings and where each came from |
|
|
92
94
|
|
|
93
95
|
`--json` on any query command emits one complete JSON document; `--plain`
|
|
@@ -181,6 +183,65 @@ flag: it would put the key into shell history and the process list. Keys are
|
|
|
181
183
|
never written to a config file and never printed in full — only as a
|
|
182
184
|
fingerprint like `sk-mafdet-live-<redacted>`.
|
|
183
185
|
|
|
186
|
+
## Saved conversations
|
|
187
|
+
|
|
188
|
+
Interactive sessions are saved on this computer, and only on this computer.
|
|
189
|
+
They are not uploaded, and Mafdet holds no copy of them.
|
|
190
|
+
|
|
191
|
+
That is a statement about the transcript, not about the model. The messages you
|
|
192
|
+
send are still sent to the API to be answered and still appear in your usage
|
|
193
|
+
records; what stays local is the saved copy.
|
|
194
|
+
|
|
195
|
+
Where they live:
|
|
196
|
+
|
|
197
|
+
| Platform | Path |
|
|
198
|
+
| ----------- | --------------------------------------------------- |
|
|
199
|
+
| Linux / WSL | `${XDG_STATE_HOME:-~/.local/state}/mafdet/sessions` |
|
|
200
|
+
| macOS | `~/Library/Application Support/mafdet/sessions` |
|
|
201
|
+
| Windows | `%LOCALAPPDATA%\mafdet\sessions` |
|
|
202
|
+
|
|
203
|
+
The files are **plain text**. A transcript contains your messages, the model's
|
|
204
|
+
replies, and any source the agent read while working — so treat a session
|
|
205
|
+
directory the way you would treat the project it came from. API keys are the
|
|
206
|
+
one exception: everything is passed through redaction on the way to disk, so a
|
|
207
|
+
key you paste into a prompt is stored as `<redacted>`. Files are created
|
|
208
|
+
`0600` and directories `0700` on Linux and macOS; Windows has no equivalent
|
|
209
|
+
mode bits and inherits the ACL of `%LOCALAPPDATA%`.
|
|
210
|
+
|
|
211
|
+
The agent cannot read these directories, even when you run `mafdet` from your
|
|
212
|
+
home directory and the store is technically inside the workspace. Otherwise an
|
|
213
|
+
agent working on one project could read another project's transcript in full.
|
|
214
|
+
|
|
215
|
+
Turning it off and cleaning up:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
mafdet --no-history # this run is not recorded at all
|
|
219
|
+
mafdet sessions list # what is saved, and the path when nothing is
|
|
220
|
+
mafdet sessions delete <id> --yes
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`--no-history` writes nothing — not an empty directory, not an index entry.
|
|
224
|
+
|
|
225
|
+
Deleting removes the local messages and this session's usage mapping. It does
|
|
226
|
+
**not** remove API usage, billing records or charges: those belong to the API
|
|
227
|
+
key, not to the transcript. And it is an ordinary file delete, not a secure
|
|
228
|
+
erase — backups, snapshots and the filesystem itself may still hold copies.
|
|
229
|
+
|
|
230
|
+
## Reconciling what a session cost
|
|
231
|
+
|
|
232
|
+
`mafdet sessions usage <id>` adds up what a conversation used from the local
|
|
233
|
+
record. Those charges are estimates, computed with the gateway's own
|
|
234
|
+
arithmetic but computed here.
|
|
235
|
+
|
|
236
|
+
`--refresh` asks the billing ledger for the real figure. It sends the request
|
|
237
|
+
IDs already in the transcript and nothing else — no messages, no title, no
|
|
238
|
+
workspace, no session ID. Requests paid for by a different API key are left
|
|
239
|
+
alone and reported, so you know to run it again with that key.
|
|
240
|
+
|
|
241
|
+
A request that the ledger has not caught up with stays `pending`, and a request
|
|
242
|
+
that never returned an ID stays `unknown`. Neither is ever shown as `0`, which
|
|
243
|
+
would read as "it was free".
|
|
244
|
+
|
|
184
245
|
## Cost and cancellation
|
|
185
246
|
|
|
186
247
|
`chat` prints tokens and an estimated charge to stderr, computed with the same
|
package/README.zh-CN.md
CHANGED
|
@@ -71,6 +71,8 @@ mafdet doctor
|
|
|
71
71
|
| `mafdet agent "<目标>" [--allow-write] [--allow-command "<前缀>"]` | 本地 Agent,默认只读 |
|
|
72
72
|
| `mafdet agent`(不带目标,需终端) | 交互会话 |
|
|
73
73
|
| `mafdet account balance\|usage\|subscription` | 钱包、用量、套餐(需 `account:read` scope) |
|
|
74
|
+
| `mafdet sessions list\|show\|usage\|delete` | 保存在这台电脑上的会话(不会调用模型) |
|
|
75
|
+
| `mafdet sessions usage <id> --refresh` | 用账单账本的权威金额替换本地估算 |
|
|
74
76
|
| `mafdet config list` | 当前生效的配置及其来源 |
|
|
75
77
|
|
|
76
78
|
查询类命令都支持 `--json`(输出一份完整 JSON 文档)与 `--plain`(无表头的 TSV,方便
|
|
@@ -156,6 +158,56 @@ Key 只从 `MAFDET_API_KEY` 读取。**刻意不提供 `--api-key` 参数**—
|
|
|
156
158
|
shell 历史和进程列表。Key 不会被写入任何配置文件,也不会完整出现在任何输出里,
|
|
157
159
|
只以 `sk-mafdet-live-<redacted>` 这样的指纹形式展示。
|
|
158
160
|
|
|
161
|
+
## 保存下来的会话
|
|
162
|
+
|
|
163
|
+
交互式会话会保存在这台电脑上,**也只在这台电脑上**。它们不会上传,Mafdet 没有副本。
|
|
164
|
+
|
|
165
|
+
这是关于**存档**的说法,不是关于模型的。你发送的消息仍然会送到 API 去作答,
|
|
166
|
+
仍然出现在你的用量记录里;留在本地的是那份保存下来的副本。
|
|
167
|
+
|
|
168
|
+
存放位置:
|
|
169
|
+
|
|
170
|
+
| 平台 | 路径 |
|
|
171
|
+
| ----------- | --------------------------------------------------- |
|
|
172
|
+
| Linux / WSL | `${XDG_STATE_HOME:-~/.local/state}/mafdet/sessions` |
|
|
173
|
+
| macOS | `~/Library/Application Support/mafdet/sessions` |
|
|
174
|
+
| Windows | `%LOCALAPPDATA%\mafdet\sessions` |
|
|
175
|
+
|
|
176
|
+
这些文件是**明文**。一份存档包含你的消息、模型的回复,以及 agent 工作时读过的任何源码——
|
|
177
|
+
所以请把会话目录当作它所对应的那个项目本身来对待。API Key 是唯一的例外:
|
|
178
|
+
所有内容在写盘前都会过一遍脱敏,你粘进提示词里的 Key 会以 `<redacted>` 的形式存下来。
|
|
179
|
+
Linux 与 macOS 上文件权限 `0600`、目录 `0700`;**Windows 没有等价的权限位**,
|
|
180
|
+
继承 `%LOCALAPPDATA%` 的 ACL。
|
|
181
|
+
|
|
182
|
+
**Agent 读不到这些目录**——即使你在家目录里运行 `mafdet`、存档实际落在工作区内也一样。
|
|
183
|
+
否则在 A 项目里工作的 agent 就能读到 B 项目会话的完整明文。
|
|
184
|
+
|
|
185
|
+
关闭与清理:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
mafdet --no-history # 这一次运行完全不记录
|
|
189
|
+
mafdet sessions list # 已保存的会话;没有时会告诉你路径
|
|
190
|
+
mafdet sessions delete <id> --yes
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`--no-history` 什么都不留——不留空目录,也不留索引条目。
|
|
194
|
+
|
|
195
|
+
删除会移除本地消息和这个会话的用量映射。它**不会**移除 API 用量、账单记录或扣费:
|
|
196
|
+
那些属于 API Key,不属于存档。而且它只是一次普通的文件删除,**不是安全擦除**——
|
|
197
|
+
备份、快照和文件系统本身仍可能保有副本。
|
|
198
|
+
|
|
199
|
+
## 对账:这次会话到底花了多少
|
|
200
|
+
|
|
201
|
+
`mafdet sessions usage <id>` 从本地记录累加一次会话的用量。那些金额是**估算**,
|
|
202
|
+
算法与网关一致,但是在本地算的。
|
|
203
|
+
|
|
204
|
+
`--refresh` 会去问账单账本要真实金额。它只发送存档里已有的 request ID,**别的什么都不发**——
|
|
205
|
+
不发消息、不发标题、不发工作区路径、不发 session ID。由另一把 API Key 支付的请求会被跳过
|
|
206
|
+
并如实告知,好让你知道该换那把 Key 再跑一次。
|
|
207
|
+
|
|
208
|
+
账本还没跟上的请求保持 `pending`,从未拿到 ID 的请求保持 `unknown`。
|
|
209
|
+
**两者都绝不显示为 `0`**——0 读起来像「免费」。
|
|
210
|
+
|
|
159
211
|
## 费用与取消
|
|
160
212
|
|
|
161
213
|
`chat` 会在 stderr 打印 token 数与预估费用,算法与网关计费一致,但**以钱包为准**。
|
package/dist/agent/loop.d.ts
CHANGED
|
@@ -88,6 +88,20 @@ export type AgentEvent = {
|
|
|
88
88
|
} | {
|
|
89
89
|
type: "text";
|
|
90
90
|
text: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* One model request's accounting, as it happens. The summary already
|
|
94
|
+
* aggregates this; the event exists so a recorder can attribute each request
|
|
95
|
+
* to the ledger row it became (CLI-024/025) - `requestId` is the gateway's
|
|
96
|
+
* x-litellm-call-id, which is unique per row in request_ledger.
|
|
97
|
+
*/
|
|
98
|
+
| {
|
|
99
|
+
type: "usage";
|
|
100
|
+
model: string;
|
|
101
|
+
requestId?: string;
|
|
102
|
+
promptTokens: number;
|
|
103
|
+
completionTokens: number;
|
|
104
|
+
costMicroUsd: bigint;
|
|
91
105
|
} | {
|
|
92
106
|
type: "rate_limited";
|
|
93
107
|
waitMs: number;
|
package/dist/agent/loop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAE1B,iBAAiB;AACjB,eAAO,MAAM,cAAc;;;IAGzB,iFAAiF;;;qBAGnD,MAAM,GAAG,SAAS;CACjD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,OAAO,cAAc,CAAC;AAEhD,MAAM,MAAM,UAAU,GAClB,WAAW,GACX,WAAW,GACX,SAAS,GACT,UAAU,GACV,WAAW,GACX,cAAc,GACd,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,UAAU,CAAC;IACvB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,kEAAkE;IAClE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,uDAAuD;IACvD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/loop.js
CHANGED
|
@@ -78,7 +78,18 @@ export async function runAgent(options) {
|
|
|
78
78
|
report.completionTokens += usage?.completion_tokens ?? 0;
|
|
79
79
|
// Cost comes from returned usage, never from the reservation: CLI-000B
|
|
80
80
|
// showed the reserve cannot see the tool schema and under-counts badly.
|
|
81
|
-
|
|
81
|
+
const turnCost = priceTurn(options.pricing, usage);
|
|
82
|
+
report.costMicroUsd += turnCost;
|
|
83
|
+
options.onEvent?.({
|
|
84
|
+
type: "usage",
|
|
85
|
+
model: options.model,
|
|
86
|
+
...(response.requestId === undefined
|
|
87
|
+
? {}
|
|
88
|
+
: { requestId: response.requestId }),
|
|
89
|
+
promptTokens: usage?.prompt_tokens ?? 0,
|
|
90
|
+
completionTokens: usage?.completion_tokens ?? 0,
|
|
91
|
+
costMicroUsd: turnCost,
|
|
92
|
+
});
|
|
82
93
|
const choice = response.choices?.[0];
|
|
83
94
|
const message = choice?.message;
|
|
84
95
|
const calls = message?.tool_calls ?? [];
|
|
@@ -198,8 +209,10 @@ async function requestWithRateLimitHandling(options, limits, body, report, clock
|
|
|
198
209
|
for (let attempt = 0;; attempt += 1) {
|
|
199
210
|
try {
|
|
200
211
|
report.modelRequests += 1;
|
|
201
|
-
const { data } = await options.client.postJson("/chat/completions", body, { signal: options.signal });
|
|
202
|
-
|
|
212
|
+
const { data, requestId } = await options.client.postJson("/chat/completions", body, { signal: options.signal });
|
|
213
|
+
// Carried on the response so the caller can tie this turn to its ledger
|
|
214
|
+
// row without the loop needing to know what a session is.
|
|
215
|
+
return { ...data, requestId };
|
|
203
216
|
}
|
|
204
217
|
catch (error) {
|
|
205
218
|
// Everything except an explicit 429 propagates. A timeout or a 5xx may
|
package/dist/agent/session.d.ts
CHANGED
|
@@ -32,6 +32,11 @@ export interface SessionOptions {
|
|
|
32
32
|
* the same events are drawn.
|
|
33
33
|
*/
|
|
34
34
|
onEvent?: (event: AgentEvent) => void;
|
|
35
|
+
/**
|
|
36
|
+
* A conversation to continue, rebuilt from a saved session (CLI-024).
|
|
37
|
+
* Appended to in place, exactly as the fresh array would be.
|
|
38
|
+
*/
|
|
39
|
+
history?: ChatMessage[];
|
|
35
40
|
}
|
|
36
41
|
export interface SessionSummary {
|
|
37
42
|
goals: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/agent/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAY,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAapE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/agent/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAY,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAapE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAwFzB;AAgHD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CA2B7D"}
|
package/dist/agent/session.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-only.d.ts","sourceRoot":"","sources":["../../../src/agent/tools/read-only.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAC;AAmB9D;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYjD;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuBjD;
|
|
1
|
+
{"version":3,"file":"read-only.d.ts","sourceRoot":"","sources":["../../../src/agent/tools/read-only.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAC;AAmB9D;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYjD;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuBjD;AAwLD,eAAO,MAAM,eAAe,EAAE,cAAc,EAM3C,CAAC"}
|
|
@@ -87,6 +87,12 @@ function walk(workspace, onFile) {
|
|
|
87
87
|
if (entry.isDirectory()) {
|
|
88
88
|
if (SKIPPED_DIRECTORIES.has(entry.name))
|
|
89
89
|
continue;
|
|
90
|
+
// The CLI's own directories, uniformly. Dot-directories are skipped
|
|
91
|
+
// anyway, which covers Linux and Windows by accident - but on macOS
|
|
92
|
+
// the state directory is `Library/Application Support/mafdet`, so
|
|
93
|
+
// without this the session ids would be listed there and nowhere else.
|
|
94
|
+
if (workspace.isOwnedByCli(full))
|
|
95
|
+
continue;
|
|
90
96
|
stack.push(full);
|
|
91
97
|
continue;
|
|
92
98
|
}
|
package/dist/api/account.d.ts
CHANGED
|
@@ -36,4 +36,47 @@ export interface Subscription {
|
|
|
36
36
|
export declare function fetchWallet(client: HttpClient): Promise<Wallet>;
|
|
37
37
|
export declare function fetchUsage(client: HttpClient, days?: number): Promise<UsageSummary>;
|
|
38
38
|
export declare function fetchSubscription(client: HttpClient): Promise<Subscription>;
|
|
39
|
+
/**
|
|
40
|
+
* CLI-027 · One settled request as the ledger holds it.
|
|
41
|
+
*
|
|
42
|
+
* The whole whitelist the server returns (CLI-026): no prompt, no response, no
|
|
43
|
+
* tool arguments, no file content, and no session id - the CLI matches on
|
|
44
|
+
* `request_id` alone, which is why none of that has to leave the machine.
|
|
45
|
+
*/
|
|
46
|
+
export interface LedgerUsageEvent {
|
|
47
|
+
request_id: string;
|
|
48
|
+
model_id: string;
|
|
49
|
+
input_tokens: number;
|
|
50
|
+
output_tokens: number;
|
|
51
|
+
platform_charge_micro_usd: string;
|
|
52
|
+
status: string;
|
|
53
|
+
created_at: string;
|
|
54
|
+
}
|
|
55
|
+
export interface UsageEventsResult {
|
|
56
|
+
readonly events: readonly LedgerUsageEvent[];
|
|
57
|
+
readonly pages: number;
|
|
58
|
+
/**
|
|
59
|
+
* True when the walk reached the end of the window.
|
|
60
|
+
*
|
|
61
|
+
* When it is false the caller stopped early, and "not found" then means "not
|
|
62
|
+
* found yet" - reporting it as "the ledger has no such request" would be a
|
|
63
|
+
* claim the walk did not earn.
|
|
64
|
+
*/
|
|
65
|
+
readonly exhausted: boolean;
|
|
66
|
+
}
|
|
67
|
+
/** Hard stop on paging, so a busy key cannot turn one command into hundreds. */
|
|
68
|
+
export declare const MAX_USAGE_EVENT_PAGES = 20;
|
|
69
|
+
/**
|
|
70
|
+
* Walk this key's settled requests, newest first.
|
|
71
|
+
*
|
|
72
|
+
* Stops as soon as every id in `wanted` has been seen: a session of three
|
|
73
|
+
* requests should cost one page, not a full sweep of the window. Passing no
|
|
74
|
+
* `wanted` set walks until the pages run out.
|
|
75
|
+
*/
|
|
76
|
+
export declare function fetchUsageEvents(client: HttpClient, options?: {
|
|
77
|
+
days?: number;
|
|
78
|
+
wanted?: ReadonlySet<string>;
|
|
79
|
+
maxPages?: number;
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}): Promise<UsageEventsResult>;
|
|
39
82
|
//# sourceMappingURL=account.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/api/account.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;GAGG;AAEH,MAAM,WAAW,MAAM;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE;QACX,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAyBD,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrE;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAMvB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,CAAC,CAKvB"}
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/api/account.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;GAGG;AAEH,MAAM,WAAW,MAAM;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE;QACX,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAyBD,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrE;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAMvB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,CAAC,CAKvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB,EAAE,MAAM,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE;IACP,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACjB,GACL,OAAO,CAAC,iBAAiB,CAAC,CAgC5B"}
|
package/dist/api/account.js
CHANGED
|
@@ -37,3 +37,43 @@ export async function fetchSubscription(client) {
|
|
|
37
37
|
.catch(explainScope);
|
|
38
38
|
return data;
|
|
39
39
|
}
|
|
40
|
+
/** Hard stop on paging, so a busy key cannot turn one command into hundreds. */
|
|
41
|
+
export const MAX_USAGE_EVENT_PAGES = 20;
|
|
42
|
+
/**
|
|
43
|
+
* Walk this key's settled requests, newest first.
|
|
44
|
+
*
|
|
45
|
+
* Stops as soon as every id in `wanted` has been seen: a session of three
|
|
46
|
+
* requests should cost one page, not a full sweep of the window. Passing no
|
|
47
|
+
* `wanted` set walks until the pages run out.
|
|
48
|
+
*/
|
|
49
|
+
export async function fetchUsageEvents(client, options = {}) {
|
|
50
|
+
const maxPages = options.maxPages ?? MAX_USAGE_EVENT_PAGES;
|
|
51
|
+
const remaining = options.wanted ? new Set(options.wanted) : undefined;
|
|
52
|
+
const events = [];
|
|
53
|
+
let cursor = null;
|
|
54
|
+
let pages = 0;
|
|
55
|
+
while (pages < maxPages) {
|
|
56
|
+
const query = new URLSearchParams();
|
|
57
|
+
if (options.days !== undefined)
|
|
58
|
+
query.set("days", String(options.days));
|
|
59
|
+
if (cursor !== null)
|
|
60
|
+
query.set("cursor", cursor);
|
|
61
|
+
const { data } = await client
|
|
62
|
+
.getJson(`/keyinfo/usage-events?${query.toString()}`, {
|
|
63
|
+
signal: options.signal,
|
|
64
|
+
})
|
|
65
|
+
.catch(explainScope);
|
|
66
|
+
pages += 1;
|
|
67
|
+
for (const event of data.data ?? []) {
|
|
68
|
+
events.push(event);
|
|
69
|
+
remaining?.delete(event.request_id);
|
|
70
|
+
}
|
|
71
|
+
if (remaining !== undefined && remaining.size === 0) {
|
|
72
|
+
return { events, pages, exhausted: true };
|
|
73
|
+
}
|
|
74
|
+
cursor = data.next_cursor ?? null;
|
|
75
|
+
if (cursor === null)
|
|
76
|
+
return { events, pages, exhausted: true };
|
|
77
|
+
}
|
|
78
|
+
return { events, pages, exhausted: false };
|
|
79
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ExitCode } from "../output/exit-codes.js";
|
|
2
|
+
import { type CommandIo } from "./runtime.js";
|
|
3
|
+
export declare function sessionsCommand(argv: readonly string[], io: CommandIo): Promise<ExitCode>;
|
|
4
|
+
export declare const DELETION_NOTICE: (id: string) => string;
|
|
5
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/commands/sessions.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAuBnD,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAgBtB,wBAAsB,eAAe,CACnC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,SAAS,GACZ,OAAO,CAAC,QAAQ,CAAC,CAenB;AAqID,eAAO,MAAM,eAAe,GAAI,IAAI,MAAM,KAAG,MAUX,CAAC"}
|