@ycodium-ai/plugin-api 0.2.2690 → 0.2.2696
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/dist/account-usage.d.ts +14 -0
- package/dist/account-usage.d.ts.map +1 -1
- package/dist/conversation-queue.d.ts +75 -0
- package/dist/conversation-queue.d.ts.map +1 -0
- package/dist/conversation-queue.js +8 -0
- package/dist/conversation-queue.js.map +1 -0
- package/dist/conversation-view.d.ts +21 -0
- package/dist/conversation-view.d.ts.map +1 -0
- package/dist/conversation-view.js +18 -0
- package/dist/conversation-view.js.map +1 -0
- package/dist/conversation.d.ts +27 -80
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +1 -11
- package/dist/conversation.js.map +1 -1
- package/dist/executor.d.ts +74 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js.map +1 -1
- package/dist/index.d.ts +4 -253
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/process-socket.d.ts +261 -0
- package/dist/process-socket.d.ts.map +1 -0
- package/dist/process-socket.js +2 -0
- package/dist/process-socket.js.map +1 -0
- package/dist/usage.d.ts +171 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +29 -0
- package/dist/usage.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 插件的进程、socket 与端口登记能力的类型。`@ycodium-ai/plugin-api` 从这里再导出,
|
|
3
|
+
* 对外导入路径不变;这个文件只放类型,运行时零依赖。
|
|
4
|
+
*
|
|
5
|
+
* @module @ycodium-ai/plugin-api/process-socket
|
|
6
|
+
*/
|
|
7
|
+
import type { PluginProxySelection } from "./index.ts";
|
|
8
|
+
/** `kill` 认的信号。不开放任意字符串——能用到的就这几个。 */
|
|
9
|
+
export type PluginProcessSignal = "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP";
|
|
10
|
+
/**
|
|
11
|
+
* 按键指程序:manifest 的白名单项写成 `{ key, program }`(或 `config:<key>` 注入一份
|
|
12
|
+
* `Record<键, 程序>`)时,插件只报键,宿主查出程序。声明里没有这个键就被拒。
|
|
13
|
+
*
|
|
14
|
+
* 用它而不是自己从 config 里读路径:那样插件手上就多了一份可能与白名单漂开的副本。
|
|
15
|
+
*/
|
|
16
|
+
export interface PluginProgramRef {
|
|
17
|
+
readonly key: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 要跑的程序。字符串形态必须逐字在 manifest 的 `process.spawn` 白名单里:裸名(宿主
|
|
21
|
+
* 在 PATH 上查)、`./` 开头的插件目录内相对路径、声明里 `config:<key>` 注入的那个值、
|
|
22
|
+
* 或 `data:<相对路径>`(插件自己的数据目录)。
|
|
23
|
+
*
|
|
24
|
+
* **四种字符串形态互不通用**,宿主按形态分别判:
|
|
25
|
+
* - 裸名(不含 `/`、`\`,也不是绝对路径,也不是 `data:` / `config:` 前缀):白名单里
|
|
26
|
+
* 必须有逐字相同的一条,然后在 PATH 上解析,且解析结果的 basename 还要与声明一致
|
|
27
|
+
* (挡住 PATH 上撞名解析到别的文件)。找不到就是 `not-on-path`。
|
|
28
|
+
* - 路径形态(含分隔符或绝对路径,且不是 `data:`):按 `pluginDir` resolve 后与白名单
|
|
29
|
+
* 里同为路径形态的条目逐一比绝对路径。
|
|
30
|
+
* - `data:<相对路径>`:白名单里必须有逐字相同的一条,再解析为 `<dataDir>/<相对路径>`。
|
|
31
|
+
* `path.normalize` 与 `realpath` 之后都必须仍以 dataDir 为前缀(拒 `..` 与 symlink
|
|
32
|
+
* 逃逸),文件必须存在且可执行;任一不满足就是 `program-unresolved`。`fs.read` 的
|
|
33
|
+
* `paths` 不认这个前缀。
|
|
34
|
+
* - 形态之间不互通:声明 `gh` 不放行 `/tmp/gh`(否则谁都能拿一个同名文件冒名
|
|
35
|
+
* 顶替),声明 `./bin/x` 也不放行裸名 `x`,声明 `data:bin/x` 也不放行 `./bin/x`。
|
|
36
|
+
*
|
|
37
|
+
* ## `config:<key>` 间接引用(`fs.read` 的 `paths` 与 `process.spawn` 的 `programs` 共用)
|
|
38
|
+
*
|
|
39
|
+
* 声明期钉不住的值(宿主装配时才算得出的 trace 目录、Codex 的 `binaryPath`……)写成
|
|
40
|
+
* `config:<key>`,指回本条 entry 的 `config[key]`。缺这个键、或值不是**非空字符串**,
|
|
41
|
+
* 等同于这条声明不存在——不静默放行成 undefined。值有三种形状:
|
|
42
|
+
* - `string`:展开成一条。
|
|
43
|
+
* - `string[]`:展开成多条(空串与非字符串项丢掉)。像「每个 provider 实例各自的
|
|
44
|
+
* 转录目录」这种条数随设置变的前缀,声明期连条数都钉不住。
|
|
45
|
+
* - `Record<键, 程序>`:**只有 `process.spawn` 的裸白名单项认这一形状**,整条展开成
|
|
46
|
+
* 多条带键项(等价于写了一串 `{ key, program }`),插件之后按 `{ key }` 报程序。
|
|
47
|
+
* `fs.read` 的 `paths` 不认它。已经写成 `{ key, program }` 的白名单项,它的
|
|
48
|
+
* `config:` 值只当 string / string[] 用——键已经由声明给了,值里再带一层键没意义。
|
|
49
|
+
*/
|
|
50
|
+
export type PluginProgramSelector = string | PluginProgramRef;
|
|
51
|
+
export interface PluginProcessRunInput {
|
|
52
|
+
readonly program: PluginProgramSelector;
|
|
53
|
+
readonly args?: readonly string[] | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* 只许 pluginDir / dataDir / cacheDir / 已声明的 `fs.read` 前缀之内;另外声明了
|
|
56
|
+
* `process.workspace` 的插件还可以落在这台机器上任一项目的工作区目录或其子目录里
|
|
57
|
+
* (`gh` 这类程序得站在仓库里才知道自己在哪)。缺省 dataDir。
|
|
58
|
+
*
|
|
59
|
+
* 比对与 `fs.read` 同一条纪律:展开 `~`、resolve、按分隔符边界切。每次 `run` /
|
|
60
|
+
* `spawn` 前宿主都会先把 `dataDir` 建出来(缺席就 recursive 创建),所以缺省 cwd
|
|
61
|
+
* 与显式传 dataDir 两条路都不会 ENOENT。
|
|
62
|
+
*/
|
|
63
|
+
readonly cwd?: string | undefined;
|
|
64
|
+
/** 叠加在宿主环境上。`PATH`、`HOME`、`YCODIUM_*` 不许覆盖,写了整次调用被拒。 */
|
|
65
|
+
readonly env?: Readonly<Record<string, string>> | undefined;
|
|
66
|
+
readonly stdin?: string | undefined;
|
|
67
|
+
/** 缺省 60000。到点先 SIGTERM 后 SIGKILL,结果带 `timedOut: true`。 */
|
|
68
|
+
readonly timeoutMs?: number | undefined;
|
|
69
|
+
/** 每条流的上限,缺省 1MB。超出即截断并置 `truncated`,不是错误。 */
|
|
70
|
+
readonly maxOutputBytes?: number | undefined;
|
|
71
|
+
}
|
|
72
|
+
export interface PluginProcessRunResult {
|
|
73
|
+
/** 被信号杀掉(含超时)没有退出码,是 null。 */
|
|
74
|
+
readonly exitCode: number | null;
|
|
75
|
+
readonly stdout: string;
|
|
76
|
+
readonly stderr: string;
|
|
77
|
+
/** 任一条流碰到 `maxOutputBytes` 就是 true。 */
|
|
78
|
+
readonly truncated: boolean;
|
|
79
|
+
readonly timedOut: boolean;
|
|
80
|
+
readonly durationMs: number;
|
|
81
|
+
}
|
|
82
|
+
export interface PluginProcessSpawnInput {
|
|
83
|
+
readonly program: PluginProgramSelector;
|
|
84
|
+
readonly args?: readonly string[] | undefined;
|
|
85
|
+
/** 与 `run` 同一条 cwd 规则,含 `process.workspace` 那一档。 */
|
|
86
|
+
readonly cwd?: string | undefined;
|
|
87
|
+
readonly env?: Readonly<Record<string, string>> | undefined;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 一个还活着的子进程。
|
|
91
|
+
*
|
|
92
|
+
* **背压**:`stdout` / `stderr` 各自后面是一条有界队列(256 块)。队列满了宿主就
|
|
93
|
+
* 停止从子进程的 pipe 读,子进程写日志的那次 write 会阻塞——**不丢块,也不无限
|
|
94
|
+
* 缓冲**。所以拿了句柄就要把两条流都读掉;只读 stdout 不读 stderr 的插件迟早会把
|
|
95
|
+
* 一个话痨子进程卡住。进程退出后队列里剩的块照样读得到,读完迭代自然结束。
|
|
96
|
+
*/
|
|
97
|
+
export interface PluginProcessHandle {
|
|
98
|
+
readonly pid: number;
|
|
99
|
+
readonly stdout: AsyncIterable<Uint8Array>;
|
|
100
|
+
readonly stderr: AsyncIterable<Uint8Array>;
|
|
101
|
+
/** 队列满时这个 promise 挂着,直到子进程读走为止。 */
|
|
102
|
+
readonly writeStdin: (chunk: Uint8Array | string) => Promise<void>;
|
|
103
|
+
/** 关掉子进程的 stdin。等 EOF 才动的程序(很多 CLI)不关就永远等下去。 */
|
|
104
|
+
readonly closeStdin: () => Promise<void>;
|
|
105
|
+
/** 缺省 SIGTERM;5 秒后仍活着宿主补 SIGKILL。 */
|
|
106
|
+
readonly kill: (signal?: PluginProcessSignal) => Promise<void>;
|
|
107
|
+
/** 正常退出给退出码;被信号杀掉是 null。 */
|
|
108
|
+
readonly exited: Promise<number | null>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 被宿主拒掉的调用,抛出的 Error 上带的结构化原因。
|
|
112
|
+
*
|
|
113
|
+
* 约束:`ctx.process` / `ctx.fs` / `ctx.credentials` 被门拦下时抛的 Error 一定带
|
|
114
|
+
* `capability`(如 `"process.spawn"`)与 `reason` 两个字段——分支照着它写,别去解析
|
|
115
|
+
* message 文本,那行字是给人读的,会变。
|
|
116
|
+
*
|
|
117
|
+
* - `undeclared` —— manifest 里根本没有这条权限。
|
|
118
|
+
* - `not-declared` —— 有 `process.spawn`,但这个程序不在白名单里。
|
|
119
|
+
* - `unknown-key` —— 报的 `{ key }` 在白名单里没有对应项。
|
|
120
|
+
* - `not-on-path` —— 白名单里的裸名在这台机器的 PATH 上找不到。
|
|
121
|
+
* - `outside-prefixes` —— 路径不在声明的 `fs.read` 前缀之内。
|
|
122
|
+
* - `cwd-outside-roots` —— cwd 不在插件自己的目录、声明的 `fs.read` 前缀、
|
|
123
|
+
* (声明了 `process.workspace` 时)这台机器的项目目录之内。
|
|
124
|
+
* - `projects-unavailable` —— 这台机器读不出项目清单,`process.workspace` 判不了。
|
|
125
|
+
* - `protected-env` —— `env` 想覆盖 `PATH` / `HOME` / `YCODIUM_*`。
|
|
126
|
+
* - `too-many-processes` —— 这个插件活着的子进程已到上限(默认 8,见 `PluginProcess`)。
|
|
127
|
+
* - `foreign-thread` —— 命令指的会话不是这个插件开的(路线图 #62)。
|
|
128
|
+
* - `not-found` —— `ctx.fs` 的目标路径不存在。与「路径在,但读不了」分得开:后者
|
|
129
|
+
* (权限、坏设备……)没有结构化原因,`reason` 留空(路线图 #14)。
|
|
130
|
+
* - `spawn-failed` —— 门都过了,但进程没起来(可执行文件不在、cwd 不存在之类)。
|
|
131
|
+
* - `too-many-sockets` —— 这个插件活着的 WebSocket 已到上限(见 `PluginSocket`)。
|
|
132
|
+
* - `socket-connect-failed` —— WebSocket 连不上(URL 不合法、握手被拒、开连接超时)。
|
|
133
|
+
* - `permission-missing` —— manifest 没有声明 `ports.register`。
|
|
134
|
+
* - `no-listener` —— `ctx.ports.register` 的端口在 127.0.0.1 上没有监听。
|
|
135
|
+
* - `not-loopback` —— 端口在听,但不是 127.0.0.1。
|
|
136
|
+
* - `too-many-ports` —— 这个插件已经登记了 4 条端口。
|
|
137
|
+
* - `program-unresolved` —— `data:` 程序规范化后不在 dataDir 内、经 symlink 逃出
|
|
138
|
+
* dataDir、文件不存在或不可执行。
|
|
139
|
+
* - `outside-workspace` —— `invocation.workspace` 的路径(解析符号链接之后)不在
|
|
140
|
+
* 这条会话的任何一个工作目录里。
|
|
141
|
+
* - `not-a-file` —— `invocation.workspace.readFile` 的目标不是普通文件。
|
|
142
|
+
* - `too-large` —— 文件超过 `maxBytes`(或 50 MiB 上限)。
|
|
143
|
+
* - `invocation-ended` —— 工具 handler 已经返回,`invocation.workspace` 不再可用。
|
|
144
|
+
*/
|
|
145
|
+
export type PluginCapabilityDeniedReason = "undeclared" | "not-declared" | "unknown-key" | "not-on-path" | "outside-prefixes" | "cwd-outside-roots" | "projects-unavailable"
|
|
146
|
+
/** 这次装配里没有编排引擎——`ycodium x` 的 CLI 进程就是这样。 */
|
|
147
|
+
| "host-unavailable"
|
|
148
|
+
/** 插件实例已经停用;旧回调不能继续写入或控制会话。 */
|
|
149
|
+
| "disposed" | "protected-env" | "foreign-thread" | "not-found" | "too-many-processes" | "spawn-failed" | "too-many-sockets" | "socket-connect-failed" | "permission-missing" | "no-listener" | "not-loopback" | "too-many-ports" | "program-unresolved" | "outside-workspace" | "not-a-file" | "too-large" | "invocation-ended"
|
|
150
|
+
/**
|
|
151
|
+
* 事实折不动,所以不让它进日志。
|
|
152
|
+
*
|
|
153
|
+
* `ctx.events.append` 在写进日志之前会拿你注册的每一块 `derivedState` 试折一遍——
|
|
154
|
+
* 用的是状态副本,真状态不动。`apply` 抛错、或者折出来的状态存不下去,这次 append
|
|
155
|
+
* 就被拒绝。
|
|
156
|
+
*
|
|
157
|
+
* 进了日志的事实删不掉:之后每一次重启重建都会再踩一次同一个坑。所以宁可在门口拒。
|
|
158
|
+
*/
|
|
159
|
+
| "does-not-fold";
|
|
160
|
+
/**
|
|
161
|
+
* 子进程能力。需要 manifest 里的 `process.spawn` 声明,且 `program` 必须在声明的
|
|
162
|
+
* 白名单内;没声明或不在白名单的调用一律 reject(ADR-0022)。
|
|
163
|
+
*
|
|
164
|
+
* **这是插件跑子进程的唯一合法通道。** 插件与服务器同进程,自己 `import
|
|
165
|
+
* "node:child_process"` 当然也起得来——但那样起的进程不在声明里、不进审计日志、
|
|
166
|
+
* 插件停用时没人杀,等于绕开安装时给人看的那份清单,视同违反安装承诺。
|
|
167
|
+
*
|
|
168
|
+
* 每个插件同时最多 8 个活着的子进程(`run` 在飞的也算,不止 `spawn`),超出当场被拒,
|
|
169
|
+
* 不排队。这个 8 是宿主默认值,不是硬顶:manifest 的 `process.spawn` 权限可以带
|
|
170
|
+
* `maxConcurrent`(1..16 的整数)把它提高,写多少就是多少——不排队、不自动重试,
|
|
171
|
+
* 数字要按这个插件实际会同时跑几个长驻子进程来定,不是越大越好(路线图 #46)。
|
|
172
|
+
* 省略字段=吃宿主默认值 8。改这个数字与改程序白名单一样,要重新过一次安装确认门。
|
|
173
|
+
* 插件停用 / 卸载 / 所在线程删除时,它起的子进程一律先 SIGTERM、5 秒后 SIGKILL。
|
|
174
|
+
*
|
|
175
|
+
* manifest 里写**多条** `process.spawn` 声明是合法的:程序白名单按顺序合并成一张表,
|
|
176
|
+
* 上限取**第一条带 `maxConcurrent` 的**那个值(同一个插件报两个不同上限没有意义)。
|
|
177
|
+
*
|
|
178
|
+
* 被拒的调用 reject 出来的 Error 带 `capability` 与 `reason`(见
|
|
179
|
+
* `PluginCapabilityDeniedReason`);起不来的进程 reason 是 `spawn-failed`。
|
|
180
|
+
*/
|
|
181
|
+
export interface PluginProcess {
|
|
182
|
+
/** 跑完收结果。长驻的东西用 `spawn`,别拿它等一个不退出的进程。 */
|
|
183
|
+
readonly run: (input: PluginProcessRunInput) => Promise<PluginProcessRunResult>;
|
|
184
|
+
readonly spawn: (input: PluginProcessSpawnInput) => Promise<PluginProcessHandle>;
|
|
185
|
+
}
|
|
186
|
+
export interface PluginSocketConnectInput {
|
|
187
|
+
/** `ws://` 或 `wss://`。别的 scheme 当场 reject。 */
|
|
188
|
+
readonly url: string;
|
|
189
|
+
/** WebSocket 子协议(`Sec-WebSocket-Protocol`)。 */
|
|
190
|
+
readonly protocols?: readonly string[] | undefined;
|
|
191
|
+
/** 走哪个代理,见 `PluginProxySelection`。省略=机器的全局默认。 */
|
|
192
|
+
readonly proxy?: PluginProxySelection | undefined;
|
|
193
|
+
/** 等 `open` 的上限,缺省 10000。到点算连接失败,`connect` reject。 */
|
|
194
|
+
readonly openTimeoutMs?: number | undefined;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 连接怎么收场的。三种来源摊平成同一份记录,插件不必分辨是谁先动的手:
|
|
198
|
+
*
|
|
199
|
+
* - 对端或本端正常关闭 —— `code` 是 WebSocket 关闭码(本端不给码时是 1000),
|
|
200
|
+
* `reason` 是对端给的那句话(没给就是 null),`error` 是 null。
|
|
201
|
+
* - 连着的时候读写出错 —— `code` 为 null,`error` 是一句给人读的说明。
|
|
202
|
+
* - 插件被停用 / 卸载 —— 宿主自己收的连接,`code` 为 null,`error` 说明是宿主关的。
|
|
203
|
+
*/
|
|
204
|
+
export interface PluginSocketClose {
|
|
205
|
+
readonly code: number | null;
|
|
206
|
+
readonly reason: string | null;
|
|
207
|
+
readonly error: string | null;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* 一条还活着的出站 WebSocket。
|
|
211
|
+
*
|
|
212
|
+
* **背压**:`messages` 后面是一条有界队列(256 帧)。队列满了宿主就不再从连接上读,
|
|
213
|
+
* TCP 层随之背压 —— 不丢帧,也不无限缓冲。所以拿了句柄就要把 `messages` 消费掉;
|
|
214
|
+
* 只连不读的插件迟早把一个话痨端点堵死。连接断开后队列里剩的帧照样读得到,读完
|
|
215
|
+
* 迭代自然结束(不是抛错 —— 断开的原因在 `closed` 里)。
|
|
216
|
+
*/
|
|
217
|
+
export interface PluginSocketHandle {
|
|
218
|
+
/** 收到的帧:文本帧是 string,二进制帧是 Uint8Array,宿主不替你解码。 */
|
|
219
|
+
readonly messages: AsyncIterable<string | Uint8Array>;
|
|
220
|
+
/** 连接已经断了再发就 reject。 */
|
|
221
|
+
readonly send: (data: string | Uint8Array) => Promise<void>;
|
|
222
|
+
/** 主动关。缺省关闭码 1000(正常关闭)。重复关是空操作。 */
|
|
223
|
+
readonly close: (code?: number, reason?: string) => Promise<void>;
|
|
224
|
+
/** 断开原因。永远 resolve,不 reject —— 断开是结果,不是错误。 */
|
|
225
|
+
readonly closed: Promise<PluginSocketClose>;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* 出站 WebSocket。**不需要任何 manifest 声明**:可达范围与 `ctx.http` 完全相同
|
|
229
|
+
* (同一台机器、同一套代理设置、同样的出网权限),而插件与服务器同进程,本就能
|
|
230
|
+
* 自己开连接 —— 为同一件事新加一档声明只会让审批卡变长,不会让谁更安全。
|
|
231
|
+
*
|
|
232
|
+
* 用它而不是自己 `new WebSocket`:宿主这条路才认代理设置、才在插件停用时把连接
|
|
233
|
+
* 收掉、才受同时连接数上限约束。自己开的连接在配了代理的机器上静默连不上,插件
|
|
234
|
+
* 卸载后还挂着。
|
|
235
|
+
*
|
|
236
|
+
* 每个插件同时最多 16 条活着的连接,超出当场被拒(`reason: "too-many-sockets"`),
|
|
237
|
+
* 不排队。这个数字不像 `ctx.process` 那样可以在 manifest 里抬高(这里根本没有声明
|
|
238
|
+
* 可写),所以一次给够:够「每个配好的实例一条连接」那种插件用,也拦得住断线不收
|
|
239
|
+
* 旧连接的泄漏。
|
|
240
|
+
*
|
|
241
|
+
* 插件停用 / 卸载 / 所在线程删除时,它开的连接一律被宿主关掉,`closed` 随之 resolve。
|
|
242
|
+
*/
|
|
243
|
+
export interface PluginSocket {
|
|
244
|
+
readonly connect: (input: PluginSocketConnectInput) => Promise<PluginSocketHandle>;
|
|
245
|
+
}
|
|
246
|
+
export interface PluginPortRegistration {
|
|
247
|
+
readonly portId: string;
|
|
248
|
+
readonly unregister: () => Promise<void>;
|
|
249
|
+
}
|
|
250
|
+
export interface PluginPorts {
|
|
251
|
+
/**
|
|
252
|
+
* 把插件在本机 127.0.0.1 上起的端口交给宿主登记表;跟插件 Scope 走,停用即注销。
|
|
253
|
+
* 需要 manifest 声明 `ports.register`。
|
|
254
|
+
*/
|
|
255
|
+
readonly register: (input: {
|
|
256
|
+
readonly kind: "workbench" | "workbench-external";
|
|
257
|
+
readonly label: string;
|
|
258
|
+
readonly port: number;
|
|
259
|
+
}) => Promise<PluginPortRegistration>;
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=process-socket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-socket.d.ts","sourceRoot":"","sources":["../src/process-socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-socket.js","sourceRoot":"","sources":["../src/process-socket.ts"],"names":[],"mappings":""}
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ycodium-ai/plugin-api/usage` —— agent 插件按**实例**提供的额度与 token 用量(ADR-0034)。
|
|
3
|
+
*
|
|
4
|
+
* 全是 `type`,外加一个纯函数 {@link parseRetryAfterMs}。宿主只做调用、合并编排账本、按价格表
|
|
5
|
+
* 算费用、单飞与「稍后再试」,再经 RPC 交给客户端;账号目录、凭据、代理、厂商地址都是插件的事。
|
|
6
|
+
*
|
|
7
|
+
* 只在用户明确点了才读:宿主不定时、不按有效期自动重查。插件只管「一次读」「一次写」。
|
|
8
|
+
*
|
|
9
|
+
* @module @ycodium-ai/plugin-api/usage
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 一段可显示的文字。`key` 在这个插件自己的 `locales/<locale>.json`(宿主命名空间
|
|
13
|
+
* `plugin:<pluginId>`)里解析,`values` 填占位符,与名片表单的 `titleKey` 同一套机制:
|
|
14
|
+
* 宿主不带兜底文案,键缺失界面明确画成缺失。`text` 是厂商给的原文(套餐名、窗口名),
|
|
15
|
+
* 原样显示,不翻译。
|
|
16
|
+
*/
|
|
17
|
+
export type ExecutorUsageText = {
|
|
18
|
+
readonly key: string;
|
|
19
|
+
readonly values?: Readonly<Record<string, string | number>>;
|
|
20
|
+
} | {
|
|
21
|
+
readonly text: string;
|
|
22
|
+
};
|
|
23
|
+
/** 一个额度窗口:已用比例 + 重置时间。 */
|
|
24
|
+
export type ExecutorQuotaWindow = {
|
|
25
|
+
/** 实例内稳定的标识,客户端用作行的 key(如 `session`、`weekly`、`limit-0`)。 */
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly label: ExecutorUsageText;
|
|
28
|
+
/** 已用百分比,0..100,由插件夹紧。 */
|
|
29
|
+
readonly usedPercent: number;
|
|
30
|
+
/** 重置时刻,ISO 8601;厂商没给就是 null。 */
|
|
31
|
+
readonly resetsAt: string | null;
|
|
32
|
+
/** 窗口长度(毫秒);说不清就缺席,不要猜。 */
|
|
33
|
+
readonly windowMs?: number;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* 一个金额类额度:剩余金额(API key 的账户余额、订阅里的积分池)。厂商没报的字段保持
|
|
37
|
+
* null,不推算。
|
|
38
|
+
*/
|
|
39
|
+
export type ExecutorQuotaBalance = {
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly label: ExecutorUsageText;
|
|
42
|
+
readonly remaining: number | null;
|
|
43
|
+
readonly used: number | null;
|
|
44
|
+
readonly limit: number | null;
|
|
45
|
+
/** 金额带 ISO 4217 币种(如 DeepSeek 余额是 CNY 或 USD);`credits` 是厂商自己的积分。 */
|
|
46
|
+
readonly unit: {
|
|
47
|
+
readonly kind: "money";
|
|
48
|
+
readonly currency: string;
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: "credits";
|
|
51
|
+
};
|
|
52
|
+
readonly resetsAt: string | null;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* 读不了的原因:
|
|
56
|
+
* - `missingCredentials`:没登录,或凭据读不到、读不懂。
|
|
57
|
+
* - `authRejected`:厂商回 401/403;刷新登录是 CLI 的事,插件不刷新。
|
|
58
|
+
* - `customEndpoint`:这个实例连的是自己的模型地址或钥匙,订阅额度不是它花的。
|
|
59
|
+
* - `unreachable`:连不上,或回了读不懂的响应;进程数已满、本次没跑起来也算。
|
|
60
|
+
* - `unsupportedLogin`:这种登录方式厂商没有额度接口(例如某家 API key 没有余额接口)。
|
|
61
|
+
* - `rateLimited`:厂商要求稍后再试,配 `retryAfterMs`。
|
|
62
|
+
*/
|
|
63
|
+
export type ExecutorQuotaUnavailableReason = "missingCredentials" | "authRejected" | "customEndpoint" | "unreachable" | "unsupportedLogin" | "rateLimited";
|
|
64
|
+
export type ExecutorQuotaReading = {
|
|
65
|
+
readonly status: "available";
|
|
66
|
+
/** 套餐名,厂商给什么写什么(如 `Max 20x`);没有就缺席。 */
|
|
67
|
+
readonly plan?: string;
|
|
68
|
+
readonly windows: ReadonlyArray<ExecutorQuotaWindow>;
|
|
69
|
+
readonly balances: ReadonlyArray<ExecutorQuotaBalance>;
|
|
70
|
+
/**
|
|
71
|
+
* 非敏感的账号标识(凭据文件路径、账号 id 都行,不要放 token)。宿主与客户端用它把
|
|
72
|
+
* 「两个实例共用同一个登录」的行合成一行。
|
|
73
|
+
*/
|
|
74
|
+
readonly accountKey?: string;
|
|
75
|
+
/** 可用的「重置额度」张数;只有支持 `redeemQuotaReset` 的 agent 填。 */
|
|
76
|
+
readonly resetCredits?: {
|
|
77
|
+
readonly availableCount: number;
|
|
78
|
+
};
|
|
79
|
+
} | {
|
|
80
|
+
readonly status: "unavailable";
|
|
81
|
+
readonly reason: ExecutorQuotaUnavailableReason;
|
|
82
|
+
/** 只在 `rateLimited` 时有意义:厂商要求等多久(毫秒)。宿主取不小于 10 秒的值。 */
|
|
83
|
+
readonly retryAfterMs?: number;
|
|
84
|
+
};
|
|
85
|
+
export type ExecutorQuotaResetResult = {
|
|
86
|
+
/** 与 Codex app-server 的 `ConsumeAccountRateLimitResetCreditOutcome` 同集合。 */
|
|
87
|
+
readonly outcome: "reset" | "nothingToReset" | "noCredit" | "alreadyRedeemed";
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* token 计数,与宿主 `UsageTokenTotals` 同口径(提案 0023 甲):三个输入桶互斥,相加是总输入;
|
|
91
|
+
* `reasoningTokens` 是 `outputTokens` 的子集,不要再加一次。没有的项填 0,不要缺席。
|
|
92
|
+
* CLI 报的 `input_tokens` 若含缓存(Codex 就是),插件在这里拆开再给。
|
|
93
|
+
*/
|
|
94
|
+
export type ExecutorTokenTotals = {
|
|
95
|
+
readonly uncachedInputTokens: number;
|
|
96
|
+
/** 缓存读。 */
|
|
97
|
+
readonly cachedInputTokens: number;
|
|
98
|
+
/** 缓存写。 */
|
|
99
|
+
readonly cacheCreationTokens: number;
|
|
100
|
+
readonly outputTokens: number;
|
|
101
|
+
readonly reasoningTokens: number;
|
|
102
|
+
};
|
|
103
|
+
export type ExecutorTokenRecord = {
|
|
104
|
+
/** 这条记录发生的时刻,ISO 8601。 */
|
|
105
|
+
readonly at: string;
|
|
106
|
+
/** 计价用的模型名;宿主按它在价格表里查,与 endpoint 无关。 */
|
|
107
|
+
readonly model: string;
|
|
108
|
+
/** CLI 侧的会话标识,用来数「有多少会话产生了花费」;没有就缺席。 */
|
|
109
|
+
readonly sessionId?: string;
|
|
110
|
+
readonly totals: ExecutorTokenTotals;
|
|
111
|
+
/** 厂商自己报了费用才填;填了宿主就用它,不再按价格表算。 */
|
|
112
|
+
readonly reportedCostUsd?: number;
|
|
113
|
+
};
|
|
114
|
+
export type ExecutorTokenUsageReading = {
|
|
115
|
+
/** 已去重:宿主不再按任何键去重。 */
|
|
116
|
+
readonly records: ReadonlyArray<ExecutorTokenRecord>;
|
|
117
|
+
/**
|
|
118
|
+
* 这批记录来自哪里。`homePath` 与 `volumeId` 一起是「同一份磁盘记录」的身份:宿主把两个
|
|
119
|
+
* 实例报出相同身份的结果只算一次(两个实例共用同一个账号目录时,否则同一份转录会记两遍)。
|
|
120
|
+
*/
|
|
121
|
+
readonly source: {
|
|
122
|
+
readonly homePath: string;
|
|
123
|
+
readonly volumeId?: string;
|
|
124
|
+
readonly status: "ok" | "missing" | "partial" | "failed";
|
|
125
|
+
readonly scannedFiles?: number;
|
|
126
|
+
readonly skippedFiles?: number;
|
|
127
|
+
readonly malformedRecords?: number;
|
|
128
|
+
/** 给用户看的一句说明(如目录不存在);不走 catalog,宿主原样带出。 */
|
|
129
|
+
readonly message?: string;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
export type ExecutorUsage = {
|
|
133
|
+
/**
|
|
134
|
+
* 当前登录账号的额度。订阅登录返回额度窗口,API key 返回剩余金额。读不了是数据
|
|
135
|
+
* (`unavailable`),不要抛;只有程序错才抛。绝不刷新或写回凭据(CLI 自己管登录的
|
|
136
|
+
* 生命周期)。CLI 自己有额度接口的优先用它。
|
|
137
|
+
*/
|
|
138
|
+
readonly readQuota?: (input: {
|
|
139
|
+
readonly signal?: AbortSignal;
|
|
140
|
+
}) => Promise<ExecutorQuotaReading>;
|
|
141
|
+
/**
|
|
142
|
+
* 时间段 `[since, until)` 内的 token 记录,来源是 CLI 自己的会话记录。去重(同一条消息在
|
|
143
|
+
* 多个文件里重复出现、fork 复制历史等)和增量缓存由插件负责。没有磁盘记录的 agent 不实现
|
|
144
|
+
* 它,用量走编排账本。
|
|
145
|
+
*/
|
|
146
|
+
readonly readTokenUsage?: (input: {
|
|
147
|
+
/** ISO 8601 时刻,含。 */
|
|
148
|
+
readonly since: string;
|
|
149
|
+
/** ISO 8601 时刻,不含。 */
|
|
150
|
+
readonly until: string;
|
|
151
|
+
readonly signal?: AbortSignal;
|
|
152
|
+
}) => Promise<ExecutorTokenUsageReading>;
|
|
153
|
+
/**
|
|
154
|
+
* 用一次厂商给的「重置额度」把当前窗口清零。只在用户明确点了才调,不自动、不重试。
|
|
155
|
+
* `idempotencyKey` 由宿主每次点击生成,原样交给厂商。厂商明确回绝(没有可用额度、窗口
|
|
156
|
+
* 本来就没用)是数据(`outcome`),不是抛错。
|
|
157
|
+
*/
|
|
158
|
+
readonly redeemQuotaReset?: (input: {
|
|
159
|
+
readonly idempotencyKey: string;
|
|
160
|
+
readonly signal?: AbortSignal;
|
|
161
|
+
}) => Promise<ExecutorQuotaResetResult>;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* 解析厂商响应里的 `Retry-After`,返回要等的毫秒数;解不出返回 null。
|
|
165
|
+
*
|
|
166
|
+
* 只认 1*DIGIT 秒数或 HTTP-date(RFC 9110 §10.2.3 的两种形态)。数字开头却不是纯秒数的
|
|
167
|
+
* 一律当没给——`Date.parse("1.5")` 会 lenient 地解成一个真实日期,那是把非法值当成了
|
|
168
|
+
* 「等到某个时刻」。过去的时刻返回 0,不留负数。
|
|
169
|
+
*/
|
|
170
|
+
export declare const parseRetryAfterMs: (header: string | null, nowMs: number) => number | null;
|
|
171
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
|
package/dist/usage.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ycodium-ai/plugin-api/usage` —— agent 插件按**实例**提供的额度与 token 用量(ADR-0034)。
|
|
3
|
+
*
|
|
4
|
+
* 全是 `type`,外加一个纯函数 {@link parseRetryAfterMs}。宿主只做调用、合并编排账本、按价格表
|
|
5
|
+
* 算费用、单飞与「稍后再试」,再经 RPC 交给客户端;账号目录、凭据、代理、厂商地址都是插件的事。
|
|
6
|
+
*
|
|
7
|
+
* 只在用户明确点了才读:宿主不定时、不按有效期自动重查。插件只管「一次读」「一次写」。
|
|
8
|
+
*
|
|
9
|
+
* @module @ycodium-ai/plugin-api/usage
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 解析厂商响应里的 `Retry-After`,返回要等的毫秒数;解不出返回 null。
|
|
13
|
+
*
|
|
14
|
+
* 只认 1*DIGIT 秒数或 HTTP-date(RFC 9110 §10.2.3 的两种形态)。数字开头却不是纯秒数的
|
|
15
|
+
* 一律当没给——`Date.parse("1.5")` 会 lenient 地解成一个真实日期,那是把非法值当成了
|
|
16
|
+
* 「等到某个时刻」。过去的时刻返回 0,不留负数。
|
|
17
|
+
*/
|
|
18
|
+
export const parseRetryAfterMs = (header, nowMs) => {
|
|
19
|
+
if (header === null)
|
|
20
|
+
return null;
|
|
21
|
+
const trimmed = header.trim();
|
|
22
|
+
if (/^\d+$/.test(trimmed))
|
|
23
|
+
return Number(trimmed) * 1000;
|
|
24
|
+
if (/^\d/.test(trimmed))
|
|
25
|
+
return null;
|
|
26
|
+
const date = Date.parse(trimmed);
|
|
27
|
+
return Number.isNaN(date) ? null : Math.max(date - nowMs, 0);
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAoKH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAqB,EAAE,KAAa,EAAiB,EAAE;IACvF,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/plugin-api",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2696",
|
|
4
4
|
"description": "Types and definePlugin for authoring Ycodium plugins. Zero runtime dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium"
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"types": "./dist/account-usage.d.ts",
|
|
33
33
|
"import": "./dist/account-usage.js"
|
|
34
34
|
},
|
|
35
|
+
"./usage": {
|
|
36
|
+
"types": "./dist/usage.d.ts",
|
|
37
|
+
"import": "./dist/usage.js"
|
|
38
|
+
},
|
|
35
39
|
"./executor": {
|
|
36
40
|
"types": "./dist/executor.d.ts",
|
|
37
41
|
"import": "./dist/executor.js"
|