@ai-workbench/remote-agent 0.8.13 → 0.8.14
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/README.md +8 -6
- package/dist/acp.d.ts +12 -7
- package/dist/acp.js +65 -41
- package/dist/broker-runtime.js +46 -20
- package/dist/broker.d.ts +4 -2
- package/dist/broker.js +18 -9
- package/dist/claude-local.d.ts +2 -1
- package/dist/claude-local.js +61 -34
- package/dist/close-diagnostics.d.ts +56 -0
- package/dist/close-diagnostics.js +104 -0
- package/dist/conversation-details.js +67 -9
- package/dist/employee-endpoint.d.ts +3 -1
- package/dist/employee-endpoint.js +8 -6
- package/dist/employee-exec.d.ts +7 -4
- package/dist/employee-exec.js +39 -29
- package/dist/employee-mcp.d.ts +6 -3
- package/dist/employee-mcp.js +75 -39
- package/dist/employee-provider.js +58 -36
- package/dist/employee-shell.d.ts +2 -0
- package/dist/employee-shell.js +17 -5
- package/dist/employee-ssh.d.ts +2 -0
- package/dist/employee-ssh.js +6 -4
- package/dist/employee-tools.d.ts +3 -1
- package/dist/employee-tools.js +6 -5
- package/dist/index.d.ts +4 -0
- package/dist/index.js +133 -44
- package/dist/model-catalog.d.ts +9 -1
- package/dist/model-catalog.js +63 -5
- package/dist/model-configuration.d.ts +14 -1
- package/dist/model-configuration.js +122 -89
- package/dist/presentation.js +2 -1
- package/dist/provider.d.ts +8 -2
- package/dist/recovery.d.ts +4 -0
- package/dist/rpc-namespace.d.ts +2 -2
- package/dist/rpc-namespace.js +2 -1
- package/package.json +1 -1
|
@@ -31,17 +31,29 @@ export declare class ModelConfigurationError extends Error {
|
|
|
31
31
|
readonly code = "MODEL_CATALOG_UNAVAILABLE";
|
|
32
32
|
constructor(reason: string, options?: ErrorOptions);
|
|
33
33
|
}
|
|
34
|
+
export type ConfigurationInformation = 'PICKER_INCOMPLETE' | 'CONFIG_UI_METADATA_INVALID' | 'UNRELATED_CONFIG_IGNORED' | 'OPTIONAL_CATEGORY_OMITTED' | 'SAME_SELECTION_UPDATE';
|
|
35
|
+
type Inform = (reason: ConfigurationInformation) => void;
|
|
36
|
+
type Roles = {
|
|
37
|
+
model?: string;
|
|
38
|
+
effort?: string;
|
|
39
|
+
};
|
|
34
40
|
/** Pure ACP configuration state. All IDs and values come from the given peer data. */
|
|
35
41
|
export declare class ModelConfiguration {
|
|
36
42
|
private readonly rpcSet;
|
|
43
|
+
private readonly inform;
|
|
37
44
|
private state;
|
|
38
45
|
private parsed?;
|
|
39
46
|
private revision;
|
|
40
47
|
private busy;
|
|
41
|
-
|
|
48
|
+
private known;
|
|
49
|
+
constructor(options: SessionConfigOption[], rpcSet: ModelConfigurationSetter, inform?: Inform, routing?: Roles);
|
|
42
50
|
get models(): readonly ModelCatalogValue[];
|
|
43
51
|
get snapshot(): ModelConfigurationSnapshot;
|
|
52
|
+
private prepare;
|
|
53
|
+
private apply;
|
|
44
54
|
update(options: SessionConfigOption[]): void;
|
|
55
|
+
/** A different ACP session cannot inherit selector-role discovery or ACKs. */
|
|
56
|
+
invalidate(clearRoles?: boolean): void;
|
|
45
57
|
private fail;
|
|
46
58
|
private checkAckRevision;
|
|
47
59
|
private set;
|
|
@@ -49,3 +61,4 @@ export declare class ModelConfiguration {
|
|
|
49
61
|
/** Call immediately before prompt; an idle/new/load/resume update withdraws the ACK. */
|
|
50
62
|
assertSelection(model: string, effort?: string): void;
|
|
51
63
|
}
|
|
64
|
+
export {};
|
|
@@ -6,86 +6,103 @@ export class ModelConfigurationError extends Error {
|
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
function unavailable(reason) { throw new ModelConfigurationError(reason); }
|
|
9
|
-
function record(value) {
|
|
10
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
11
|
-
}
|
|
9
|
+
function record(value) { return value !== null && typeof value === 'object' && !Array.isArray(value); }
|
|
12
10
|
function text(value) { return typeof value === 'string' && value.trim().length > 0; }
|
|
13
|
-
function label(value) {
|
|
14
|
-
if (!text(value.name))
|
|
15
|
-
|
|
16
|
-
if (value.description !== undefined && value.description !== null && typeof value.description !== 'string')
|
|
17
|
-
unavailable('配置说明无效');
|
|
11
|
+
function label(value, inform) {
|
|
12
|
+
if (!text(value.name) || value.description !== undefined && value.description !== null && typeof value.description !== 'string')
|
|
13
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
18
14
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const seen = new Set();
|
|
15
|
+
/** Picker entries are presentation, not an exhaustive list of legal setter values. */
|
|
16
|
+
function select(option, inform) {
|
|
17
|
+
if (option.type !== 'select' || !text(option.currentValue))
|
|
18
|
+
unavailable('模型或推理配置没有有效的选择器与实际当前值');
|
|
19
|
+
const values = [], seen = new Set(), groups = new Set();
|
|
20
|
+
let flat = false, grouped = false;
|
|
24
21
|
const add = (value) => {
|
|
25
|
-
if (!record(value) || !text(value.value)
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if (!record(value) || !text(value.value)) {
|
|
23
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
label(value, inform);
|
|
28
27
|
if (seen.has(value.value))
|
|
29
|
-
|
|
28
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
30
29
|
seen.add(value.value);
|
|
31
|
-
values.push({ value: value.value, name: value.name, ...(value.description ===
|
|
30
|
+
values.push({ value: value.value, name: typeof value.name === 'string' ? value.name : '', ...(typeof value.description === 'string' || value.description === null ? { description: value.description } : {}) });
|
|
32
31
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
if (!Array.isArray(option.options) || !option.options.length)
|
|
33
|
+
inform('PICKER_INCOMPLETE');
|
|
34
|
+
else
|
|
35
|
+
for (const entry of option.options) {
|
|
36
|
+
if (record(entry) && 'group' in entry) {
|
|
37
|
+
grouped = true;
|
|
38
|
+
if (flat)
|
|
39
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
40
|
+
if (typeof entry.group !== 'string' || groups.has(entry.group))
|
|
41
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
42
|
+
if (typeof entry.group === 'string')
|
|
43
|
+
groups.add(entry.group);
|
|
44
|
+
label(entry, inform);
|
|
45
|
+
if (!Array.isArray(entry.options)) {
|
|
46
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (!entry.options.length)
|
|
50
|
+
inform('PICKER_INCOMPLETE');
|
|
51
|
+
for (const value of entry.options)
|
|
52
|
+
add(value);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
flat = true;
|
|
56
|
+
if (grouped)
|
|
57
|
+
inform('CONFIG_UI_METADATA_INVALID');
|
|
58
|
+
add(entry);
|
|
59
|
+
}
|
|
45
60
|
}
|
|
46
|
-
else
|
|
47
|
-
add(entry);
|
|
48
|
-
}
|
|
49
61
|
if (!seen.has(option.currentValue))
|
|
50
|
-
|
|
62
|
+
inform('PICKER_INCOMPLETE');
|
|
51
63
|
return { id: option.id, currentValue: option.currentValue, values };
|
|
52
64
|
}
|
|
53
|
-
function parse(options) {
|
|
65
|
+
function parse(options, known, inform) {
|
|
54
66
|
if (!Array.isArray(options) || !options.length)
|
|
55
|
-
unavailable('
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
models.push(selector);
|
|
72
|
-
if (option.category === 'thought_level')
|
|
73
|
-
efforts.push(selector);
|
|
67
|
+
unavailable('远端没有提供可核对的模型配置入口');
|
|
68
|
+
const entries = options.filter(record), counts = new Map();
|
|
69
|
+
for (const option of entries) {
|
|
70
|
+
label(option, inform);
|
|
71
|
+
if (text(option.id))
|
|
72
|
+
counts.set(option.id, (counts.get(option.id) ?? 0) + 1);
|
|
73
|
+
}
|
|
74
|
+
const role = (category, id, required) => {
|
|
75
|
+
let candidates = entries.filter(option => option.category === category);
|
|
76
|
+
const known = id ? entries.filter(option => option.id === id) : [];
|
|
77
|
+
if (known.length) {
|
|
78
|
+
if (candidates.some(option => option.id !== id))
|
|
79
|
+
unavailable('同一会话的模型或推理配置入口存在冲突,不能改用另一个入口的值作回执');
|
|
80
|
+
candidates = known;
|
|
81
|
+
if (known[0].category !== category)
|
|
82
|
+
inform('OPTIONAL_CATEGORY_OMITTED');
|
|
74
83
|
}
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
unavailable('模型或推理等级配置不是选择器');
|
|
84
|
+
if (candidates.length !== 1) {
|
|
85
|
+
if (!required && !candidates.length)
|
|
86
|
+
return;
|
|
87
|
+
unavailable(candidates.length ? '模型或推理配置入口不唯一' : '没有可靠的模型配置入口,不能猜测配置标识');
|
|
80
88
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
const option = candidates[0];
|
|
90
|
+
if (!text(option.id) || (counts.get(option.id) ?? 0) !== 1)
|
|
91
|
+
unavailable('模型或推理配置标识无效或重复');
|
|
92
|
+
return select(option, inform);
|
|
93
|
+
};
|
|
94
|
+
const model = role('model', known.model, true), effort = role('thought_level', known.effort, false);
|
|
95
|
+
if (model.id === effort?.id)
|
|
96
|
+
unavailable('模型和推理等级不能共用同一个配置入口');
|
|
97
|
+
for (const option of options)
|
|
98
|
+
if (!record(option) || option.id !== model.id && option.id !== effort?.id) {
|
|
99
|
+
if (!record(option) || !text(option.id) || !['select', 'boolean'].includes(option.type))
|
|
100
|
+
inform('UNRELATED_CONFIG_IGNORED');
|
|
101
|
+
}
|
|
102
|
+
return { model, effort };
|
|
103
|
+
}
|
|
104
|
+
function sameSelection(a, b) {
|
|
105
|
+
return !!a && !!b && a.model.id === b.model.id && a.model.currentValue === b.model.currentValue && a.effort?.id === b.effort?.id && a.effort?.currentValue === b.effort?.currentValue;
|
|
89
106
|
}
|
|
90
107
|
function freeze(value, seen = new WeakSet()) {
|
|
91
108
|
if (value !== null && typeof value === 'object' && !seen.has(value)) {
|
|
@@ -99,12 +116,17 @@ function freeze(value, seen = new WeakSet()) {
|
|
|
99
116
|
/** Pure ACP configuration state. All IDs and values come from the given peer data. */
|
|
100
117
|
export class ModelConfiguration {
|
|
101
118
|
rpcSet;
|
|
119
|
+
inform;
|
|
102
120
|
state;
|
|
103
121
|
parsed;
|
|
104
122
|
revision = 0;
|
|
105
123
|
busy = false;
|
|
106
|
-
|
|
124
|
+
known = {};
|
|
125
|
+
constructor(options, rpcSet, inform = () => { }, routing) {
|
|
107
126
|
this.rpcSet = rpcSet;
|
|
127
|
+
this.inform = inform;
|
|
128
|
+
if (routing)
|
|
129
|
+
this.known = { ...routing };
|
|
108
130
|
this.update(options);
|
|
109
131
|
}
|
|
110
132
|
get models() {
|
|
@@ -113,30 +135,36 @@ export class ModelConfiguration {
|
|
|
113
135
|
return this.state.models;
|
|
114
136
|
}
|
|
115
137
|
get snapshot() { return this.state; }
|
|
138
|
+
prepare(options) {
|
|
139
|
+
const copy = structuredClone(options), parsed = parse(copy, this.known, this.inform);
|
|
140
|
+
return { copy: copy, parsed };
|
|
141
|
+
}
|
|
142
|
+
apply({ copy, parsed }) {
|
|
143
|
+
const same = sameSelection(this.parsed, parsed), confirmed = same && this.state?.confirmed === true;
|
|
144
|
+
if (!same)
|
|
145
|
+
this.revision++;
|
|
146
|
+
else
|
|
147
|
+
this.inform('SAME_SELECTION_UPDATE');
|
|
148
|
+
this.parsed = parsed;
|
|
149
|
+
this.known = { model: parsed.model.id, ...parsed.effort ? { effort: parsed.effort.id } : {} };
|
|
150
|
+
this.state = freeze({ configOptions: copy, models: parsed.model.values, modelConfigId: parsed.model.id, model: parsed.model.currentValue,
|
|
151
|
+
...(parsed.effort ? { effortConfigId: parsed.effort.id, effort: parsed.effort.currentValue } : {}), effortAvailable: !!parsed.effort, confirmed });
|
|
152
|
+
}
|
|
116
153
|
update(options) {
|
|
117
|
-
this.revision++;
|
|
118
|
-
let copy = [];
|
|
119
154
|
try {
|
|
120
|
-
|
|
121
|
-
const copied = structuredClone(options);
|
|
122
|
-
if (Array.isArray(copied))
|
|
123
|
-
copy = copied;
|
|
124
|
-
const parsed = parse(copied);
|
|
125
|
-
this.parsed = parsed;
|
|
126
|
-
this.state = freeze({
|
|
127
|
-
configOptions: copy, models: parsed.model.values,
|
|
128
|
-
modelConfigId: parsed.model.id, model: parsed.model.currentValue,
|
|
129
|
-
...(parsed.effort ? { effortConfigId: parsed.effort.id, effort: parsed.effort.currentValue } : {}),
|
|
130
|
-
effortAvailable: !!parsed.effort, confirmed: false,
|
|
131
|
-
});
|
|
155
|
+
this.apply(this.prepare(options));
|
|
132
156
|
}
|
|
133
157
|
catch (cause) {
|
|
134
158
|
const error = cause instanceof ModelConfigurationError ? cause : new ModelConfigurationError('配置数据无法复制或解析', { cause });
|
|
159
|
+
this.revision++;
|
|
135
160
|
this.parsed = undefined;
|
|
136
|
-
this.state = freeze({ configOptions:
|
|
161
|
+
this.state = freeze({ configOptions: [], models: [], effortAvailable: false, confirmed: false, failure: { code: error.code, message: error.message } });
|
|
137
162
|
throw error;
|
|
138
163
|
}
|
|
139
164
|
}
|
|
165
|
+
/** A different ACP session cannot inherit selector-role discovery or ACKs. */
|
|
166
|
+
invalidate(clearRoles = true) { if (clearRoles)
|
|
167
|
+
this.known = {}; this.update([]); }
|
|
140
168
|
fail(error) {
|
|
141
169
|
this.state = freeze({ ...this.state, confirmed: false, failure: { code: error.code, message: error.message } });
|
|
142
170
|
}
|
|
@@ -145,7 +173,7 @@ export class ModelConfiguration {
|
|
|
145
173
|
unavailable(`${stage}回执之后收到其他配置更新,原选择未获确认`);
|
|
146
174
|
}
|
|
147
175
|
async set(id, value, stage) {
|
|
148
|
-
const revision = this.revision;
|
|
176
|
+
const revision = this.revision, modelId = this.parsed?.model.id, effortId = this.parsed?.effort?.id;
|
|
149
177
|
let response;
|
|
150
178
|
try {
|
|
151
179
|
response = await this.rpcSet(id, value);
|
|
@@ -153,11 +181,16 @@ export class ModelConfiguration {
|
|
|
153
181
|
catch (cause) {
|
|
154
182
|
throw new ModelConfigurationError(`${stage}配置请求失败,未获得远端确认`, { cause });
|
|
155
183
|
}
|
|
156
|
-
if (revision !== this.revision)
|
|
157
|
-
unavailable(`${stage}配置请求期间收到其他配置更新,无法确认回执顺序`);
|
|
158
184
|
if (!record(response) || !Array.isArray(response.configOptions))
|
|
159
185
|
unavailable(`${stage}配置回执缺少完整配置列表`);
|
|
160
|
-
this.
|
|
186
|
+
const prepared = this.prepare(response.configOptions);
|
|
187
|
+
if (prepared.parsed.model.id !== modelId || stage === '推理等级' && prepared.parsed.effort && prepared.parsed.effort.id !== effortId)
|
|
188
|
+
unavailable('配置回执改用了其他入口,原请求没有得到确认');
|
|
189
|
+
// Notifications can precede their own setter ACK. Only a conflicting real
|
|
190
|
+
// selection, rather than unrelated/same-value UI updates, invalidates it.
|
|
191
|
+
if (revision !== this.revision && !sameSelection(this.parsed, prepared.parsed))
|
|
192
|
+
unavailable(`${stage}配置请求期间收到不同的实际配置,无法确认回执顺序`);
|
|
193
|
+
this.apply(prepared);
|
|
161
194
|
return this.revision;
|
|
162
195
|
}
|
|
163
196
|
async select(model, effort) {
|
|
@@ -169,7 +202,7 @@ export class ModelConfiguration {
|
|
|
169
202
|
if (!this.parsed)
|
|
170
203
|
unavailable('当前远端配置列表无效');
|
|
171
204
|
if (!this.parsed.model.values.some(entry => entry.value === model))
|
|
172
|
-
|
|
205
|
+
this.inform('PICKER_INCOMPLETE');
|
|
173
206
|
let ackRevision = await this.set(this.parsed.model.id, model, '模型');
|
|
174
207
|
this.checkAckRevision(ackRevision, '模型');
|
|
175
208
|
if (this.state.model !== model)
|
|
@@ -179,7 +212,7 @@ export class ModelConfiguration {
|
|
|
179
212
|
if (!selector)
|
|
180
213
|
unavailable('远端没有提供实际推理等级选择器');
|
|
181
214
|
if (!selector.values.some(entry => entry.value === effort))
|
|
182
|
-
|
|
215
|
+
this.inform('PICKER_INCOMPLETE');
|
|
183
216
|
ackRevision = await this.set(selector.id, effort, '推理等级');
|
|
184
217
|
this.checkAckRevision(ackRevision, '推理等级');
|
|
185
218
|
if (this.state.model !== model)
|
package/dist/presentation.js
CHANGED
|
@@ -61,8 +61,9 @@ export function employeeFailure(code, brand = 'codex') {
|
|
|
61
61
|
ACP_CLIENT_LOST: '我需要管理员核对并结束遗留的主机会话;当前保留原进程,没有代答旧审批。',
|
|
62
62
|
ONESHOT_CONTEXT_REQUIRED: '首版单次模式不支持图片或系统与开发者上下文,请改用会话模式。',
|
|
63
63
|
MODEL_CONFIGURATION_UNSUPPORTED: '单次模式不支持确认当前模型与推理等级,本轮未发送;请改用会话模式。',
|
|
64
|
+
INPUT_DELIVERY_UNCONFIRMED: '上一轮输入的处理结果尚未确认;没有自动重发,你的原话仍保留,请先核对技术详情。',
|
|
64
65
|
MODEL_SELECTION_REQUIRED: '旧远端恢复记录没有明确模型选择,本轮未发送;请新建会话并选择模型。',
|
|
65
|
-
MODEL_RESOLUTION_UNCONFIRMED: '
|
|
66
|
+
MODEL_RESOLUTION_UNCONFIRMED: '主机目录尚未给出所选模型的唯一具体型号,本轮未发送;你的原话仍保留,请联系管理员核对模型目录。',
|
|
66
67
|
REMOTE_CLEANUP_UNCONFIRMED: '原主机会话的清理结果尚未确认,已阻断继续发送;请联系管理员核对,不能自动重开。',
|
|
67
68
|
};
|
|
68
69
|
if (messages[code])
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CloseCause, CloseDiagnostics } from './close-diagnostics.ts';
|
|
1
2
|
import type { AgentApp } from '@agentclientprotocol/sdk';
|
|
2
3
|
import type { AgentApp as ExtendedAgentApp } from '@agentclientprotocol/sdk/unstable';
|
|
3
4
|
import type { ConnectState, ConnectNeed, ConnectApi as LConnectApi, ConnectionState, LoginPromptState } from '@ai-workbench/connect/api';
|
|
@@ -36,7 +37,7 @@ export interface Runtime {
|
|
|
36
37
|
broker?: BrokerTransport;
|
|
37
38
|
oneShot?: OneShotRuntime;
|
|
38
39
|
loginRequired?: () => Promise<void>;
|
|
39
|
-
dispose?: () => Promise<void>;
|
|
40
|
+
dispose?: (cause?: CloseCause) => Promise<void>;
|
|
40
41
|
binding?: {
|
|
41
42
|
bindingId: string;
|
|
42
43
|
workspaceId: string;
|
|
@@ -47,8 +48,9 @@ export interface Runtime {
|
|
|
47
48
|
details?: DetailChannel;
|
|
48
49
|
recoveredSession?: AcpRecovery;
|
|
49
50
|
restartNotice?: string;
|
|
50
|
-
detach?: () => Promise<void>;
|
|
51
|
+
detach?: (cause?: CloseCause) => Promise<void>;
|
|
51
52
|
restartInputIds?: readonly string[];
|
|
53
|
+
freshSessionConfirmed?: boolean;
|
|
52
54
|
saveCheckpoint?: (id: string, acp: AcpRecovery) => Promise<boolean>;
|
|
53
55
|
detailContext?: () => {
|
|
54
56
|
turn: string | number | null;
|
|
@@ -63,8 +65,12 @@ export interface Runtime {
|
|
|
63
65
|
};
|
|
64
66
|
employeeExecution?: (params: unknown, signal?: AbortSignal) => Promise<Record<string, unknown>>;
|
|
65
67
|
employeePresentation?: string;
|
|
68
|
+
closeDiagnostics?: CloseDiagnostics;
|
|
66
69
|
}
|
|
67
70
|
export interface RuntimeRequest extends Invocation {
|
|
71
|
+
closeDiagnostics?: CloseDiagnostics;
|
|
72
|
+
requireFreshSession?: boolean;
|
|
73
|
+
previousContextSha256?: string;
|
|
68
74
|
preflightFailureRecorded?: boolean;
|
|
69
75
|
recordEarlyFailure?: (error: unknown, stage: SourceAdmissionStage) => Promise<void>;
|
|
70
76
|
userInputIds?: readonly string[];
|
package/dist/recovery.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ export interface AcpRecovery {
|
|
|
4
4
|
capabilities: AgentCapabilities;
|
|
5
5
|
modelConfiguration?: {
|
|
6
6
|
configOptions: SessionConfigOption[];
|
|
7
|
+
selectorRoles?: {
|
|
8
|
+
model?: string;
|
|
9
|
+
effort?: string;
|
|
10
|
+
};
|
|
7
11
|
resolvedEvidence?: {
|
|
8
12
|
modelValue: string;
|
|
9
13
|
resolvedModel: string;
|
package/dist/rpc-namespace.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Stream } from '@agentclientprotocol/sdk/unstable';
|
|
1
|
+
import type { Stream, AnyMessage } from '@agentclientprotocol/sdk/unstable';
|
|
2
2
|
/** Public Stream only. Server request/approval IDs are never changed. */
|
|
3
|
-
export declare function isolateRpcIds(stream: Stream): Stream;
|
|
3
|
+
export declare function isolateRpcIds(stream: Stream, onWrite?: (message: AnyMessage) => void): Stream;
|
package/dist/rpc-namespace.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { NeedError } from "./remote.js";
|
|
3
3
|
/** Public Stream only. Server request/approval IDs are never changed. */
|
|
4
|
-
export function isolateRpcIds(stream) {
|
|
4
|
+
export function isolateRpcIds(stream, onWrite) {
|
|
5
5
|
const prefix = randomUUID() + '/';
|
|
6
6
|
const pending = new Map();
|
|
7
7
|
const readable = stream.readable.pipeThrough(new TransformStream({ transform(message, controller) {
|
|
@@ -30,6 +30,7 @@ export function isolateRpcIds(stream) {
|
|
|
30
30
|
}
|
|
31
31
|
const writer = stream.writable.getWriter();
|
|
32
32
|
try {
|
|
33
|
+
onWrite?.(outgoing);
|
|
33
34
|
await writer.write(outgoing);
|
|
34
35
|
}
|
|
35
36
|
finally {
|