atomix-cli 1.2.0 → 1.3.0
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/cli.js +5420 -349
- package/dist/session.d.ts +256 -3
- package/dist/session.js +4983 -345
- package/dist/session.mjs +4980 -344
- package/dist/tui.mjs +1221 -255
- package/package.json +3 -1
package/dist/session.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* 会话库的公开类型面(docs/session-api-v1.md §4 / §6)。
|
|
3
5
|
*
|
|
@@ -46,12 +48,79 @@ export interface SessionCoreApi {
|
|
|
46
48
|
}): unknown;
|
|
47
49
|
dispose(): Promise<void>;
|
|
48
50
|
}
|
|
51
|
+
export type PermissionDecision = "allow" | "deny";
|
|
52
|
+
/** 无人值守下一次工具权限请求(core `tool:permission:request` 的公开子集) */
|
|
53
|
+
export interface PermissionRequestInfo {
|
|
54
|
+
agentId: string;
|
|
55
|
+
toolName: string;
|
|
56
|
+
title: string;
|
|
57
|
+
/** 权限说明:字符串或结构化内容(Edit / Write 是 patch 对象) */
|
|
58
|
+
content: string | Record<string, unknown>;
|
|
59
|
+
/** core 提供的可选操作字典(仅供展示;应答只有 allow / deny 两档) */
|
|
60
|
+
options: Record<string, string>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 无人值守权限策略(session-api-v1 §9.7,S5):自动应答器遇权限请求先问它,'allow' = 同意一次,'deny' = 拒绝。
|
|
64
|
+
* 抛错 / 返回其他值一律按 deny(fail-closed 不变,只是把"关"之前的窗口让给调用方)。缺省 = 一律 deny
|
|
65
|
+
*/
|
|
66
|
+
export type PermissionPolicy = (req: PermissionRequestInfo) => PermissionDecision | Promise<PermissionDecision>;
|
|
67
|
+
export interface AskQuestionOptionInfo {
|
|
68
|
+
label: string;
|
|
69
|
+
description: string;
|
|
70
|
+
}
|
|
71
|
+
export interface AskQuestionInfo {
|
|
72
|
+
question: string;
|
|
73
|
+
/** 问题标签(最多 12 字符) */
|
|
74
|
+
header: string;
|
|
75
|
+
/** 2–4 个选项 */
|
|
76
|
+
options: AskQuestionOptionInfo[];
|
|
77
|
+
multiSelect: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** 无人值守下一次 AskUserQuestion(core `ask:question:request` 的公开子集) */
|
|
80
|
+
export interface QuestionRequestInfo {
|
|
81
|
+
agentId: string;
|
|
82
|
+
/** 1–4 个问题 */
|
|
83
|
+
questions: AskQuestionInfo[];
|
|
84
|
+
}
|
|
85
|
+
/** 问题文本 → 答案(多选用逗号分隔;也可以是选项之外的自由文本);空对象 = 跳过(记入 blocked) */
|
|
86
|
+
export type QuestionAnswers = Record<string, string>;
|
|
87
|
+
/** 无人值守提问策略:抛错 / 非对象一律按跳过 */
|
|
88
|
+
export type QuestionPolicy = (req: QuestionRequestInfo) => QuestionAnswers | Promise<QuestionAnswers>;
|
|
89
|
+
/** FormUI 字段(公开面只固定公共属性;type 对应 core FormField 的各成员,其余属性原样透传) */
|
|
90
|
+
export interface FormFieldInfo {
|
|
91
|
+
type: string;
|
|
92
|
+
key?: string;
|
|
93
|
+
label?: string;
|
|
94
|
+
required?: boolean;
|
|
95
|
+
help?: string;
|
|
96
|
+
}
|
|
97
|
+
/** 无人值守下一次 FormUI(core `form:request` 的公开子集) */
|
|
98
|
+
export interface FormRequestInfo {
|
|
99
|
+
agentId: string;
|
|
100
|
+
title: string;
|
|
101
|
+
surface: "inline" | "dock";
|
|
102
|
+
submitLabel: string;
|
|
103
|
+
fields: FormFieldInfo[];
|
|
104
|
+
}
|
|
105
|
+
/** 字段 key → 值;submitted:false = 跳过(记入 blocked) */
|
|
106
|
+
export interface FormAnswer {
|
|
107
|
+
values: Record<string, unknown>;
|
|
108
|
+
submitted: boolean;
|
|
109
|
+
}
|
|
110
|
+
/** 无人值守表单策略:抛错 / 非对象一律按跳过 */
|
|
111
|
+
export type FormPolicy = (req: FormRequestInfo) => FormAnswer | Promise<FormAnswer>;
|
|
49
112
|
export interface SessionCoreOptions {
|
|
50
113
|
cwd: string;
|
|
51
114
|
/** 缺省:interactive → step-by-step;headless → free-style(与现行 -p 一致,决策 1) */
|
|
52
115
|
permissionMode?: PermissionMode;
|
|
53
116
|
/** true = 有人值守(权限/提问/表单由宿主 UI 应答);false(默认)= 无人值守,自动应答器 fail-closed 接管(决策 1) */
|
|
54
117
|
interactive?: boolean;
|
|
118
|
+
/** 无人值守下的权限策略;interactive 时忽略 */
|
|
119
|
+
permissionPolicy?: PermissionPolicy;
|
|
120
|
+
/** 无人值守下的 AskUserQuestion 策略;缺省跳过(空答案);interactive 时忽略 */
|
|
121
|
+
questionPolicy?: QuestionPolicy;
|
|
122
|
+
/** 无人值守下的 FormUI 策略;缺省跳过(未提交);interactive 时忽略 */
|
|
123
|
+
formPolicy?: FormPolicy;
|
|
55
124
|
/** 一进程多会话宿主传 true(core multiSession,session-api-v1 §3.2);交互入口保持缺省 */
|
|
56
125
|
multiSession?: boolean;
|
|
57
126
|
/** 缺省跟随 interactive */
|
|
@@ -60,6 +129,11 @@ export interface SessionCoreOptions {
|
|
|
60
129
|
hooks?: boolean;
|
|
61
130
|
systemPrompt?: string;
|
|
62
131
|
logLevel?: LogLevel;
|
|
132
|
+
/**
|
|
133
|
+
* 宿主侧 sessionId 占用检查(同步):/clear 换新 id 时 core 会问候选 id 是否已被本宿主占用(serve 传进程内会话表),
|
|
134
|
+
* true 则重新生成。与提交切换在同一同步段完成(session-api-v1 §10)
|
|
135
|
+
*/
|
|
136
|
+
isSessionIdTaken?: (sessionId: string) => boolean;
|
|
63
137
|
}
|
|
64
138
|
export interface StartSessionOptions {
|
|
65
139
|
/** 会话级 harness 覆盖(不读不写项目态);缺省读 <cwd>/.atomix/harness-state.json;名字不存在直接抛错 */
|
|
@@ -120,6 +194,7 @@ export interface SessionModelInfo {
|
|
|
120
194
|
}
|
|
121
195
|
export interface AtomixSession<C extends SessionCoreApi = SessionCoreApi> {
|
|
122
196
|
readonly core: C;
|
|
197
|
+
/** 当前 sessionId(实时值:send('/clear') 后换新 id;ready.sessionId 保持打开时的原值) */
|
|
123
198
|
readonly sessionId: string;
|
|
124
199
|
readonly cwd: string;
|
|
125
200
|
readonly harness: string;
|
|
@@ -163,11 +238,33 @@ export type StreamEvent = {
|
|
|
163
238
|
toolName: string;
|
|
164
239
|
title: string;
|
|
165
240
|
content: string;
|
|
166
|
-
}
|
|
241
|
+
}
|
|
242
|
+
/** serve 的 permissionPrompt:'ask' 下带 requestId / content / options,用 session.permit 应答 */
|
|
243
|
+
| {
|
|
167
244
|
type: "permission_request";
|
|
168
245
|
agentId: string;
|
|
169
246
|
toolName: string;
|
|
170
247
|
title: string;
|
|
248
|
+
requestId?: string;
|
|
249
|
+
content?: string | Record<string, unknown>;
|
|
250
|
+
options?: Record<string, string>;
|
|
251
|
+
}
|
|
252
|
+
/** AskUserQuestion;serve 的 permissionPrompt:'ask' 下带 requestId,用 session.answer 应答 */
|
|
253
|
+
| {
|
|
254
|
+
type: "question_request";
|
|
255
|
+
agentId: string;
|
|
256
|
+
questions: AskQuestionInfo[];
|
|
257
|
+
requestId?: string;
|
|
258
|
+
}
|
|
259
|
+
/** FormUI;serve 的 permissionPrompt:'ask' 下带 requestId,用 session.form 应答 */
|
|
260
|
+
| {
|
|
261
|
+
type: "form_request";
|
|
262
|
+
agentId: string;
|
|
263
|
+
title: string;
|
|
264
|
+
surface: "inline" | "dock";
|
|
265
|
+
submitLabel: string;
|
|
266
|
+
fields: FormFieldInfo[];
|
|
267
|
+
requestId?: string;
|
|
171
268
|
} | {
|
|
172
269
|
type: "agent_start";
|
|
173
270
|
taskId: string;
|
|
@@ -198,6 +295,13 @@ export type StreamEvent = {
|
|
|
198
295
|
type: "error";
|
|
199
296
|
errorType: string;
|
|
200
297
|
message: string;
|
|
298
|
+
}
|
|
299
|
+
/** /clear 完成:上下文已清空且换了新 sessionId(旧会话历史文件保留,可 resume);之后按新 id 寻址(serve 下旧 id 仍可用) */
|
|
300
|
+
| {
|
|
301
|
+
type: "session_cleared";
|
|
302
|
+
sessionId: string;
|
|
303
|
+
previousSessionId: string | null;
|
|
304
|
+
usage: Usage;
|
|
201
305
|
};
|
|
202
306
|
/** 历史会话条目(resume.ts listSessions) */
|
|
203
307
|
export interface SessionEntry {
|
|
@@ -217,6 +321,14 @@ export interface ServeOpenParams {
|
|
|
217
321
|
sessionId?: string;
|
|
218
322
|
systemPrompt?: string;
|
|
219
323
|
hooks?: boolean;
|
|
324
|
+
/**
|
|
325
|
+
* 人在回路(§9.7):'refuse'(缺省)= 无人值守 fail-closed:权限直接拒、AskUser 空答、FormUI 不提交;
|
|
326
|
+
* 'ask' = 把 permission_request / question_request / form_request(带 requestId)推给持有者,
|
|
327
|
+
* 等 session.permit / session.answer / session.form 应答;permitTimeoutMs 内未应答、会话无主、本轮结束一律按拒绝 / 跳过
|
|
328
|
+
*/
|
|
329
|
+
permissionPrompt?: "refuse" | "ask";
|
|
330
|
+
/** 覆盖本会话的应答等待时长(缺省取 serve 的 --permit-timeout,60000) */
|
|
331
|
+
permitTimeoutMs?: number;
|
|
220
332
|
}
|
|
221
333
|
export type ServeRequest = {
|
|
222
334
|
id: string | number;
|
|
@@ -245,6 +357,45 @@ export type ServeRequest = {
|
|
|
245
357
|
session: string;
|
|
246
358
|
force?: boolean;
|
|
247
359
|
};
|
|
360
|
+
}
|
|
361
|
+
/** ws 多连接:接管无主(持有者已断线)的会话,成为持有者并按序回放断线期间缓冲的事件;有主 → conflict */
|
|
362
|
+
| {
|
|
363
|
+
id: string | number;
|
|
364
|
+
op: "session.attach";
|
|
365
|
+
params: {
|
|
366
|
+
session: string;
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/** 应答 permissionPrompt:'ask' 下的权限请求;requestId 不存在或已超时 → not_found;只有持有者能应答 */
|
|
370
|
+
| {
|
|
371
|
+
id: string | number;
|
|
372
|
+
op: "session.permit";
|
|
373
|
+
params: {
|
|
374
|
+
session: string;
|
|
375
|
+
requestId: string;
|
|
376
|
+
decision: PermissionDecision;
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
/** 应答 question_request:answers = 问题文本 → 答案(多选逗号分隔);空对象 = 跳过 */
|
|
380
|
+
| {
|
|
381
|
+
id: string | number;
|
|
382
|
+
op: "session.answer";
|
|
383
|
+
params: {
|
|
384
|
+
session: string;
|
|
385
|
+
requestId: string;
|
|
386
|
+
answers: QuestionAnswers;
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
/** 应答 form_request:values = 字段 key → 值;submitted 缺省 true,false = 跳过 */
|
|
390
|
+
| {
|
|
391
|
+
id: string | number;
|
|
392
|
+
op: "session.form";
|
|
393
|
+
params: {
|
|
394
|
+
session: string;
|
|
395
|
+
requestId: string;
|
|
396
|
+
values: Record<string, unknown>;
|
|
397
|
+
submitted?: boolean;
|
|
398
|
+
};
|
|
248
399
|
} | {
|
|
249
400
|
id: string | number;
|
|
250
401
|
op: "session.list";
|
|
@@ -278,6 +429,10 @@ export interface ServeSessionInfo {
|
|
|
278
429
|
model: SessionModelInfo;
|
|
279
430
|
/** 进行中 + 排队中的 send 数 */
|
|
280
431
|
pending: number;
|
|
432
|
+
/** 本连接是否持有该会话(stdio 恒 true) */
|
|
433
|
+
owned: boolean;
|
|
434
|
+
/** 当前无主(持有者已断线,等待 attach 或 detach-ttl 到期;stdio 恒 false) */
|
|
435
|
+
detached: boolean;
|
|
281
436
|
}
|
|
282
437
|
export interface ServeOpenResult extends ServeSessionInfo {
|
|
283
438
|
notes: string[];
|
|
@@ -287,12 +442,30 @@ export interface ServeOpenResult extends ServeSessionInfo {
|
|
|
287
442
|
export interface ServeSendResult extends SendResult {
|
|
288
443
|
sessionId: string;
|
|
289
444
|
}
|
|
445
|
+
export interface ServeAttachResult extends ServeSessionInfo {
|
|
446
|
+
/** 回放的缓冲事件条数 */
|
|
447
|
+
replayed: number;
|
|
448
|
+
/** 缓冲超限被丢弃的最早事件条数(>0 时回放前先推一条 dropped 事件) */
|
|
449
|
+
dropped: number;
|
|
450
|
+
}
|
|
290
451
|
export type ServeResult = ServeOpenResult | ServeSendResult | {
|
|
291
452
|
sessionId: string;
|
|
292
453
|
interrupted: number;
|
|
293
454
|
} | {
|
|
294
455
|
sessionId: string;
|
|
295
456
|
closed: true;
|
|
457
|
+
} | ServeAttachResult | {
|
|
458
|
+
sessionId: string;
|
|
459
|
+
requestId: string;
|
|
460
|
+
decision: PermissionDecision;
|
|
461
|
+
} | {
|
|
462
|
+
sessionId: string;
|
|
463
|
+
requestId: string;
|
|
464
|
+
answered: true;
|
|
465
|
+
} | {
|
|
466
|
+
sessionId: string;
|
|
467
|
+
requestId: string;
|
|
468
|
+
submitted: boolean;
|
|
296
469
|
} | {
|
|
297
470
|
sessions: ServeSessionInfo[];
|
|
298
471
|
} | {
|
|
@@ -312,7 +485,8 @@ export type ServeResult = ServeOpenResult | ServeSendResult | {
|
|
|
312
485
|
/**
|
|
313
486
|
* error.type:'protocol'(不是合法 JSON / 不是对象 / 缺 id(id 须为非空 string 或安全整数)/ id 在途重复 / 未知 op
|
|
314
487
|
* / 超单行上限 / 正在关闭)| 'args'(参数缺失或类型不对:boolean / number 严格按类型,cwd 必须是目录)
|
|
315
|
-
* | 'not_found'(session 不存在)| 'conflict'(session id 已打开)
|
|
488
|
+
* | 'not_found'(session 不存在 / permit 的 requestId 不存在或已超时)| 'conflict'(session id 已打开 / attach 有主会话)
|
|
489
|
+
* | 'forbidden'(ws 多连接:对非本连接持有的会话 send / interrupt / close;无主会话须先 attach)
|
|
316
490
|
* | 'limit'(活跃会话数 / 在途请求数超上限;shutdown / ping / interrupt / force close 不受在途上限约束)
|
|
317
491
|
* | 'init'(打开失败)| 'internal'
|
|
318
492
|
*/
|
|
@@ -330,10 +504,24 @@ export type ServeResponse = {
|
|
|
330
504
|
message: string;
|
|
331
505
|
};
|
|
332
506
|
};
|
|
507
|
+
/** 接管无主会话时,断线期间缓冲超限被丢弃的最早事件条数(回放前推一条) */
|
|
508
|
+
export interface ServeDroppedEvent {
|
|
509
|
+
type: "dropped";
|
|
510
|
+
count: number;
|
|
511
|
+
}
|
|
512
|
+
export type ServeEvent = StreamEvent | ServeDroppedEvent;
|
|
333
513
|
export interface ServeEventRecord {
|
|
334
514
|
type: "event";
|
|
335
515
|
session: string;
|
|
336
|
-
event:
|
|
516
|
+
event: ServeEvent;
|
|
517
|
+
}
|
|
518
|
+
/** `--listen` 模式 stdout 的 ready 记录附带接入信息(宿主 spawn 后读第一行即可) */
|
|
519
|
+
export interface ServeListenInfo {
|
|
520
|
+
url: string;
|
|
521
|
+
/** 未用 --token-file 时在此回传(自动生成或 --token 指定) */
|
|
522
|
+
token?: string;
|
|
523
|
+
/** --token-file:token 已写入该文件(0600),不回传 */
|
|
524
|
+
tokenFile?: string;
|
|
337
525
|
}
|
|
338
526
|
export interface ServeServerRecord {
|
|
339
527
|
type: "server";
|
|
@@ -341,8 +529,65 @@ export interface ServeServerRecord {
|
|
|
341
529
|
version: string;
|
|
342
530
|
pid: number;
|
|
343
531
|
cwd: string;
|
|
532
|
+
listen?: ServeListenInfo;
|
|
533
|
+
/** 每个连接的 ready 记录带:单条请求字节上限(stdio 单行 / ws 单帧);stdout 的两条 server 记录不带 */
|
|
534
|
+
limits?: {
|
|
535
|
+
maxRequestBytes: number;
|
|
536
|
+
};
|
|
344
537
|
}
|
|
345
538
|
export type ServeRecord = ServeResponse | ServeEventRecord | ServeServerRecord;
|
|
539
|
+
/** ws url(`ws://host:port`,token 走 Authorization 头)或带 stdin / stdout 的对象(ChildProcess 或任意流对) */
|
|
540
|
+
export type ServeTarget = string | {
|
|
541
|
+
stdin: NodeJS.WritableStream | null;
|
|
542
|
+
stdout: NodeJS.ReadableStream | null;
|
|
543
|
+
};
|
|
544
|
+
export interface ServeClientOptions {
|
|
545
|
+
/** ws 接入 token(stdout ready 记录里的 listen.token);stdio 不需要 */
|
|
546
|
+
token?: string;
|
|
547
|
+
/** 握手 + 等 ready 记录的超时(缺省 10000) */
|
|
548
|
+
connectTimeoutMs?: number;
|
|
549
|
+
/** 每个请求的缺省超时(缺省不超时:send 可能很长);到点以 type:'timeout' 拒绝,迟到的响应丢弃 */
|
|
550
|
+
requestTimeoutMs?: number;
|
|
551
|
+
}
|
|
552
|
+
export interface ServeRequestOptions {
|
|
553
|
+
/** 覆盖本次请求的超时 */
|
|
554
|
+
timeoutMs?: number;
|
|
555
|
+
}
|
|
556
|
+
/** 连接断开信息:ws 带关闭码与原因;stdio 只表示 stdout 结束 */
|
|
557
|
+
export interface ServeCloseInfo {
|
|
558
|
+
code?: number;
|
|
559
|
+
reason?: string;
|
|
560
|
+
}
|
|
561
|
+
export interface ServeClient {
|
|
562
|
+
/** 连接后收到的第一条 ready 记录 */
|
|
563
|
+
readonly ready: ServeServerRecord;
|
|
564
|
+
readonly closed: boolean;
|
|
565
|
+
/** 服务端 ready 记录里给的单条请求字节上限(旧服务端没给时取 1 MiB) */
|
|
566
|
+
readonly maxRequestBytes: number;
|
|
567
|
+
/**
|
|
568
|
+
* 发一个请求,resolve 为 result;ok:false 时 reject ServeRequestError(带 error.type);连接断开时在途请求全部以
|
|
569
|
+
* type:'closed' reject;序列化后超过 maxRequestBytes 的请求在本地以 type:'protocol' reject、不上线(服务端对超限
|
|
570
|
+
* 请求回的是没有 id 的 protocol 错误,客户端无法关联)
|
|
571
|
+
*/
|
|
572
|
+
request<R = ServeResult>(op: ServeOp, params?: Record<string, unknown>, opts?: ServeRequestOptions): Promise<R>;
|
|
573
|
+
/** 会话事件(所有会话;按 rec.session 自行分流);返回取消订阅函数 */
|
|
574
|
+
onEvent(listener: (rec: ServeEventRecord) => void): () => void;
|
|
575
|
+
/** 服务端回的无法关联到请求的错误(id 为 null 的 response):本客户端只发合法请求,正常不会出现;出现即协议层异常 */
|
|
576
|
+
onProtocolError(listener: (error: {
|
|
577
|
+
type: string;
|
|
578
|
+
message: string;
|
|
579
|
+
}) => void): () => void;
|
|
580
|
+
/** ready 之后的 server 记录(shutdown) */
|
|
581
|
+
onServer(listener: (rec: ServeServerRecord) => void): () => void;
|
|
582
|
+
onClose(listener: (info: ServeCloseInfo) => void): () => void;
|
|
583
|
+
/** 关闭连接:ws 发 1000;stdio 结束 stdin(服务端排空后退出) */
|
|
584
|
+
close(): Promise<void>;
|
|
585
|
+
}
|
|
586
|
+
declare class ServeRequestError extends Error {
|
|
587
|
+
readonly type: string;
|
|
588
|
+
readonly op: ServeOp;
|
|
589
|
+
constructor(type: string, message: string, op: ServeOp);
|
|
590
|
+
}
|
|
346
591
|
/** 一步到位:构造 + 装配(无人值守缺省)。模型未配置 / session id 非法 / harness 不存在直接抛错 */
|
|
347
592
|
export declare const openSession: (opts: OpenSessionOptions) => Promise<AtomixSession>;
|
|
348
593
|
/** 两段式第一步:只构造 core(交互入口在此之后跑模型向导)。返回不透明句柄 */
|
|
@@ -373,5 +618,13 @@ export declare const DEFAULT_PERMISSION_MODE: PermissionMode;
|
|
|
373
618
|
export declare const parsePermissionMode: (arg: string | undefined) => PermissionMode | null;
|
|
374
619
|
/** ~/.atomix(或 ATOMIX_ROOT) */
|
|
375
620
|
export declare const getAtomixRoot: () => string;
|
|
621
|
+
/** serve 薄客户端:ws url 或带 stdin/stdout 的子进程 → request(op, params) + onEvent;两种传输同一用法 */
|
|
622
|
+
export declare const connectServe: (target: ServeTarget, opts?: ServeClientOptions) => Promise<ServeClient>;
|
|
623
|
+
/** request 的 ok:false 结果:type = 协议的 error.type('closed' = 连接断开) */
|
|
624
|
+
declare const ServeRequestError$1: typeof ServeRequestError;
|
|
625
|
+
|
|
626
|
+
export {
|
|
627
|
+
ServeRequestError$1 as ServeRequestError,
|
|
628
|
+
};
|
|
376
629
|
|
|
377
630
|
export {};
|