@ai-workbench/remote-agent 0.8.27 → 0.8.28
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 +4 -2
- package/dist/acp.js +2 -0
- package/dist/index.js +29 -21
- package/dist/input.d.ts +7 -1
- package/dist/input.js +53 -34
- package/dist/presentation.d.ts +1 -1
- package/dist/presentation.js +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# AI Workbench 远程助手 · @ai-workbench/remote-agent@0.8.
|
|
1
|
+
# AI Workbench 远程助手 · @ai-workbench/remote-agent@0.8.28 · 插件 → 添加插件
|
|
2
2
|
|
|
3
3
|
通过官方 DSH 插件入口使用 Claude(远程主机)与 Codex(远程主机)。登录和工作区来源由“远程主机连接”组件提供;员工在原生工作区和模型菜单中选择文件夹与型号。
|
|
4
4
|
|
|
@@ -14,7 +14,9 @@ Claude 本机 Bash 会单独消费员工桥代理的控制诊断,不把它交
|
|
|
14
14
|
|
|
15
15
|
每轮启动一个新助手进程,按原生会话编号恢复上下文;不接回旧进程或重放上一轮输入。主机会话始终使用创建时保存的主机和目录;工作区之后的选择只影响新会话。
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
同一 DSH 会话切换 Claude/Codex 时,切回会接本品牌最近的远端会话,并补充它尚未见过的可见对话;首次使用某品牌则带入全部可见历史。工具内部状态、推理和技术详情不转交。历史超出既有 `acpMaxMessageBytes` 容量时,只带能容纳的最近完整轮,并在技术详情说明省略数量;当前输入保持完整,超限仍明确失败。没有新增设置、重试或时限。
|
|
18
|
+
|
|
19
|
+
断线会结束本轮;已派发的操作可能已部分执行,请先检查文件。恢复连接后可在原会话继续。旧进程清理和技术详情记录尽力而为,不阻止发起下一轮;如果上一轮仍占用原生线程,续接会明确失败并说明本轮输入未发送,不新建替代线程。自动定位、清理同一会话/线程的已断开旧进程仍需 S 提供公开能力,当前不会自动杀旧进程或冒称已恢复。原生本机会话恢复的兼容性及实际设备结果见本轮交付证据,未验证项不作为已通过。
|
|
18
20
|
|
|
19
21
|
DSH 启动和打开模型菜单时读取一次主机型号列表。发送时不再查询目录或预核所选型号;所选型号不可用时,请在模型菜单重新选择。
|
|
20
22
|
|
package/dist/acp.js
CHANGED
|
@@ -605,6 +605,8 @@ export function acpNeed(error) {
|
|
|
605
605
|
if (error instanceof NeedError)
|
|
606
606
|
return error;
|
|
607
607
|
if (error instanceof acp.RequestError) {
|
|
608
|
+
if (record(error.data)?.reason === 'thread_active_writer')
|
|
609
|
+
return new NeedError('REMOTE_SESSION_BUSY', employeeFailure('REMOTE_SESSION_BUSY'), '原远端线程仍被占用;需要按同一DSH会话和远端线程定位已断开的旧broker并确认释放;RPC 错误码 ' + error.code);
|
|
608
610
|
// Host SDK1.9 uses Internal error + data.details for thrown adapter errors.
|
|
609
611
|
// Only fixed codes cross this boundary; arbitrary detail strings are never copied.
|
|
610
612
|
for (const value of [error.message, record(error.data)?.details]) {
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { StreamMapper } from "./mapping.js";
|
|
|
12
12
|
import { connectProvider } from "./provider.js";
|
|
13
13
|
import { brokerFactory } from "./broker.js";
|
|
14
14
|
import { AGENTS, CODEX_AGENT } from "./agents.js";
|
|
15
|
-
import { prepareInput,
|
|
15
|
+
import { prepareInput, prepareContinuation } from "./input.js";
|
|
16
16
|
import { NeedError } from "./remote.js";
|
|
17
17
|
import { employeeFailure } from "./presentation.js";
|
|
18
18
|
import { createRemoteDetails } from "./remote-details.js";
|
|
@@ -53,16 +53,16 @@ function modelResolutionLabel(configuration) {
|
|
|
53
53
|
: `具体型号:${configuration.resolvedModel}`;
|
|
54
54
|
}
|
|
55
55
|
function readPointer(options, agent) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return;
|
|
65
|
-
|
|
56
|
+
for (let index = options.messages.length - 1; index >= 0; index--) {
|
|
57
|
+
const message = options.messages[index];
|
|
58
|
+
if (message.role !== 'assistant' || message.source.provider !== options.provider)
|
|
59
|
+
continue;
|
|
60
|
+
const envelope = message.source.replayState;
|
|
61
|
+
const pointer = envelope?.response;
|
|
62
|
+
if (pointer?.version !== 2 || pointer.agent !== agent.id || pointer.dshSessionId !== options.sessionId || ![pointer.identity, pointer.cwd, pointer.sessionId].every(value => typeof value === 'string' && value.length > 0) || pointer.contextSha256 !== undefined && typeof pointer.contextSha256 !== 'string')
|
|
63
|
+
continue;
|
|
64
|
+
return { pointer: pointer, index };
|
|
65
|
+
}
|
|
66
66
|
}
|
|
67
67
|
// A reporting failure can wrap the original admission error. Preserve its
|
|
68
68
|
// already-safe login snapshot even when a newer preflight delivery is unknown.
|
|
@@ -197,16 +197,17 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
197
197
|
throw failure.reason;
|
|
198
198
|
}
|
|
199
199
|
async *stream(options) {
|
|
200
|
+
let promptDispatched = false;
|
|
200
201
|
try {
|
|
201
|
-
yield* this.generate(options);
|
|
202
|
+
yield* this.generate(options, () => { promptDispatched = true; });
|
|
202
203
|
}
|
|
203
204
|
catch (error) {
|
|
204
205
|
if (error instanceof ModelConfigurationError)
|
|
205
|
-
throw new LlmError(employeeFailure(error.code, this.agent.loginProvider), error.code, { cause: error });
|
|
206
|
+
throw new LlmError(employeeFailure(error.code, this.agent.loginProvider, promptDispatched), error.code, { cause: error });
|
|
206
207
|
if (error instanceof NeedError) {
|
|
207
208
|
const rpc = /RPC 错误码 (-?\d+)/u.exec(error.requires)?.[1];
|
|
208
209
|
const evidence = failureEvidenceSummary(error);
|
|
209
|
-
const message = connectNeedMessage(error) ?? employeeFailure(error.code, this.agent.loginProvider);
|
|
210
|
+
const message = connectNeedMessage(error) ?? employeeFailure(error.code, this.agent.loginProvider, promptDispatched);
|
|
210
211
|
const login = originalLoginFailure(error);
|
|
211
212
|
let diagnostic = login?.technical ? JSON.stringify(login.technical) : '';
|
|
212
213
|
if (login?.technical && this.reportLoginFailure) {
|
|
@@ -220,10 +221,10 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
220
221
|
}
|
|
221
222
|
throw new LlmError(message, error.code, { cause: new Error(`诊断代码:${error.code};${error.requires}` + (evidence ? ';' + evidence : '') + (diagnostic ? ';' + diagnostic : '')) });
|
|
222
223
|
}
|
|
223
|
-
throw new LlmError(employeeFailure('TURN_FAILED', this.agent.loginProvider), 'TURN_FAILED', { cause: error });
|
|
224
|
+
throw new LlmError(employeeFailure('TURN_FAILED', this.agent.loginProvider, promptDispatched), 'TURN_FAILED', { cause: error });
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
|
-
async *generate(original) {
|
|
227
|
+
async *generate(original, onPromptDispatched) {
|
|
227
228
|
if (original.purpose)
|
|
228
229
|
throw new NeedError('PURPOSE_UNSUPPORTED', '此远程模型不处理后台标题或上下文整理请求,未发送模型请求', '独立的后台请求能力');
|
|
229
230
|
if (this.lifetime.signal.aborted)
|
|
@@ -272,12 +273,10 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
272
273
|
try {
|
|
273
274
|
if (!Number.isSafeInteger(config.acpMaxMessageBytes) || config.acpMaxMessageBytes < 1)
|
|
274
275
|
throw new NeedError('SETTINGS_REQUIRED', '远程模型连接设置无效,请联系管理员检查', '有效的acpMaxMessageBytes');
|
|
275
|
-
const
|
|
276
|
+
const checkpoint = readPointer(options, this.agent), previous = checkpoint?.pointer;
|
|
276
277
|
employeeNoticeShown = !!key && this.employeeNoticeSessions.has(key) || false;
|
|
277
278
|
if (employeeNoticeShown && key)
|
|
278
279
|
this.employeeNoticeSessions.add(key);
|
|
279
|
-
const last = options.messages.findLast(message => message.role === 'assistant');
|
|
280
|
-
const missingPointer = !!last && !previous;
|
|
281
280
|
live = undefined;
|
|
282
281
|
const configuration = JSON.stringify([config.acpMaxMessageBytes, config.brokerMaxFrameBytes, config.brokerControlMaxBytes, config.employeeShellKillGraceMs]);
|
|
283
282
|
Object.assign(request, { acpMaxMessageBytes: config.acpMaxMessageBytes, resumeSessionId: previous?.sessionId, sessionId: options.sessionId, mode, hostSource: previous?.hostSource, cwd: previous?.cwd, identity: previous?.identity, bindingId: previous?.bindingId, workspaceId: previous?.workspaceId, agent: this.agent, signal, brokerSettings: Object.freeze({ brokerMaxFrameBytes: config.brokerMaxFrameBytes, brokerControlMaxBytes: config.brokerControlMaxBytes }) });
|
|
@@ -307,7 +306,6 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
307
306
|
// New Codex transport scopes are independent of the native context digest.
|
|
308
307
|
if (contextChanged)
|
|
309
308
|
request.contextSha256 = undefined;
|
|
310
|
-
const claudeContextChanged = !!previous && !codex && previous.contextSha256 !== contextSha256;
|
|
311
309
|
if (mode === 'session' && Buffer.byteLength(JSON.stringify({ prompt: input.prompt, systemPrompt: input.systemPrompt }), 'utf8') > config.acpMaxMessageBytes)
|
|
312
310
|
throw new NeedError('ACP_MESSAGE_TOO_LARGE', '本轮输入超过已设置的会话消息容量,未截断或发送', '管理员调整acpMaxMessageBytes');
|
|
313
311
|
selected = this.modelPresentation.find(options.model) ?? { id: options.model, value: options.model, name: options.model, resolvedModel: null, reasoning: { options: [], defaultValue: null, defaultKnown: false }, source: null };
|
|
@@ -327,12 +325,14 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
327
325
|
}
|
|
328
326
|
if (previous && !runtime.hostSource && (previous.identity !== runtime.identity || previous.cwd !== runtime.cwd || previous.bindingId && previous.bindingId !== runtime.binding?.bindingId || previous.workspaceId && previous.workspaceId !== runtime.binding?.workspaceId))
|
|
329
327
|
throw new NeedError('SESSION_CONTEXT_MISMATCH', '原会话的员工主机或工作区已改变,请新建会话', '原会话的可信目标和工作区');
|
|
330
|
-
input =
|
|
328
|
+
input = await prepareContinuation({ ...options, messages: options.messages.slice((checkpoint?.index ?? -1) + 1) }, input, this.readImage, { maxBytes: config.acpMaxMessageBytes, host: runtime.hostWorkspace });
|
|
331
329
|
if (runtime.hostWorkspace && mode === 'session' && Buffer.byteLength(JSON.stringify({ prompt: input.prompt, systemPrompt: input.systemPrompt }), 'utf8') > config.acpMaxMessageBytes)
|
|
332
330
|
throw new NeedError('ACP_MESSAGE_TOO_LARGE', '本轮输入超过已设置的会话消息容量,未截断或发送', '管理员调整acpMaxMessageBytes');
|
|
333
331
|
const details = runtime.details ?? await createRemoteDetails({ warn: line => console.warn(line) }).open({ sessionId: options.sessionId ?? 'unscoped', provider: this.agent.loginProvider, identity: runtime.identity, connection: runtime.connection });
|
|
334
332
|
recordInformation();
|
|
335
333
|
request.recordEarlyFailure = undefined;
|
|
334
|
+
if (input.historyTransfer)
|
|
335
|
+
details.record({ kind: 'session', severity: input.historyTransfer.omittedRounds ? 'warning' : 'info', code: input.historyTransfer.omittedRounds ? 'HISTORY_TRANSFER_TRIMMED' : 'HISTORY_TRANSFER', summary: input.historyTransfer.omittedRounds ? `可见历史超过既有会话消息容量,保留最近${input.historyTransfer.retainedRounds}轮,省略较早${input.historyTransfer.omittedRounds}轮;当前输入完整保留。` : '已补充当前远端会话尚未见过的可见对话,未重放工具或审批。', payload: input.historyTransfer });
|
|
336
336
|
if (runtime.hostWorkspace)
|
|
337
337
|
details.record({ kind: 'session', severity: 'info', code: 'HOST_WORKSPACE_CONTEXT', summary: '本轮模型工作区上下文及审批会话目录使用已确认的主机目录。', payload: { source: 'host', cwd: runtime.hostWorkspace.cwd } });
|
|
338
338
|
const mapper = new StreamMapper(mode === 'session' && !contextChanged ? (previous ? (previous.usageSnapshot ?? null) : undefined) : undefined, observation => details.record(observation));
|
|
@@ -438,6 +438,12 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
438
438
|
remoteAttempted = true;
|
|
439
439
|
try {
|
|
440
440
|
await session.start(runtime.execution?.hostCwd ?? runtime.cwd, previous?.sessionId, modelSignal, { systemPrompt: input.systemPrompt, ...(runtime.execution ? { employeeRouting: runtime.execution.routing } : {}), ...(codex ? { codexNewSessionOnly: true } : {}), ...(runtime.employeeExecutionMeta ? { employeeExecution: runtime.employeeExecutionMeta } : {}) }, input.prompt);
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
details.record({ kind: 'session', severity: 'action-required', code: 'SESSION_START_FAILED', summary: '远端会话建立或恢复失败,本轮用户输入未发送。', payload: { operation: previous ? 'resume-or-load' : 'new', reason: closeCode(error, 'ACP_FAILED'), promptDispatched: false } });
|
|
444
|
+
throw error;
|
|
445
|
+
}
|
|
446
|
+
try {
|
|
441
447
|
const actual = await session.selectModel(selected.value, options.reasoningEffort, modelSignal);
|
|
442
448
|
// This lease is tied to the trusted host-user and instance/epoch.
|
|
443
449
|
// Its mapping and this turn's exact setter ACK are different facts.
|
|
@@ -532,6 +538,8 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
532
538
|
yield { type: 'finish', reason: { kind: stop === 'max_tokens' || stop === 'max_turn_requests' ? 'max-tokens' : 'stop' }, replayState: { response: pointer } };
|
|
533
539
|
}
|
|
534
540
|
catch (error) {
|
|
541
|
+
if (session && session.promptDispatchCount > promptBaseline)
|
|
542
|
+
onPromptDispatched();
|
|
535
543
|
turnFailure = error;
|
|
536
544
|
runtime?.closeDiagnostics?.record({ layer: 'adapter', initiator: 'adapter.turn-failure', reason: closeCode(error, signal.aborted ? 'ABORTED' : 'TURN_FAILED'), action: 'failure' });
|
|
537
545
|
recordInformation();
|
package/dist/input.d.ts
CHANGED
|
@@ -11,6 +11,9 @@ export interface HistoryTransfer {
|
|
|
11
11
|
offloadedImagePlaceholders: number;
|
|
12
12
|
omittedReasoningBlocks: number;
|
|
13
13
|
reasoningOmissionReason: 'dsh-internal-reasoning';
|
|
14
|
+
retainedRounds: number;
|
|
15
|
+
omittedRounds: number;
|
|
16
|
+
maxBytes: number;
|
|
14
17
|
}
|
|
15
18
|
export interface HostWorkspacePresentation {
|
|
16
19
|
readonly cwd: string;
|
|
@@ -32,7 +35,10 @@ export interface PreparedInput {
|
|
|
32
35
|
/** Invocation-only model context; never modifies the native session/history. */
|
|
33
36
|
export declare function projectHostWorkspaceInput(input: PreparedInput, host?: HostWorkspacePresentation): PreparedInput;
|
|
34
37
|
/** Role-labelled public history only; never serialize source/replay/tool internals. */
|
|
35
|
-
export declare function prepareContinuation(options: GenerateOptions, input: PreparedInput, readImage
|
|
38
|
+
export declare function prepareContinuation(options: GenerateOptions, input: PreparedInput, readImage: ImageReader | undefined, capacity: {
|
|
39
|
+
maxBytes: number;
|
|
40
|
+
host?: HostWorkspacePresentation;
|
|
41
|
+
}): Promise<PreparedInput>;
|
|
36
42
|
/** The attachment service supplies verified bytes; client paths never cross SSH. */
|
|
37
43
|
export declare function prepareInput(options: GenerateOptions, readImage?: ImageReader): Promise<PreparedInput>;
|
|
38
44
|
export {};
|
package/dist/input.js
CHANGED
|
@@ -50,45 +50,64 @@ async function publicBlock(block, options, readImage, history = false) {
|
|
|
50
50
|
throw new NeedError(history ? 'HISTORY_CONTENT_UNSUPPORTED' : 'INPUT_TYPE_REQUIRED', `我需要此${history ? '历史' : '输入'}类型的远程转接能力:${block.type};本轮未新建或发送`, '对应类型的公开ACP输入映射;内部推理及工具记录不可降为用户要求');
|
|
51
51
|
}
|
|
52
52
|
/** Role-labelled public history only; never serialize source/replay/tool internals. */
|
|
53
|
-
export async function prepareContinuation(options, input, readImage) {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const runtimeSnapshots = new Map(input.runtimeSnapshots);
|
|
61
|
-
const historyTransfer = { scope: 'visible-user-assistant-text-and-images', textBlocks: 0, imageBlocks: 0, offloadedImagePlaceholders: 0, omittedReasoningBlocks: 0, reasoningOmissionReason: 'dsh-internal-reasoning' };
|
|
62
|
-
for (const message of messages.slice(0, after + 1)) {
|
|
63
|
-
if (message.role === 'system' || message.role === 'developer')
|
|
53
|
+
export async function prepareContinuation(options, input, readImage, capacity) {
|
|
54
|
+
const after = options.messages.findLastIndex(message => message.role === 'assistant');
|
|
55
|
+
const groups = [];
|
|
56
|
+
for (const message of options.messages.slice(0, after + 1)) {
|
|
57
|
+
// Runtime snapshots, approval answers and tool state are not employee-visible
|
|
58
|
+
// conversation. Current runtime/system context stays on its original path.
|
|
59
|
+
if (message.role !== 'assistant' && (message.role !== 'user' || message.source?.kind !== 'user'))
|
|
64
60
|
continue;
|
|
65
|
-
if (message.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
61
|
+
if (!message.content.some(block => block.type === 'text' || block.type === 'image'))
|
|
62
|
+
continue;
|
|
63
|
+
if (message.role === 'user' || !groups.length)
|
|
64
|
+
groups.push([]);
|
|
65
|
+
groups.at(-1).push(message);
|
|
66
|
+
}
|
|
67
|
+
const base = projectHostWorkspaceInput(input, capacity.host);
|
|
68
|
+
if (!groups.length)
|
|
69
|
+
return base;
|
|
70
|
+
const historyTransfer = { scope: 'visible-user-assistant-text-and-images', textBlocks: 0, imageBlocks: 0, offloadedImagePlaceholders: 0, omittedReasoningBlocks: 0, reasoningOmissionReason: 'dsh-internal-reasoning', retainedRounds: 0, omittedRounds: groups.length, maxBytes: capacity.maxBytes };
|
|
71
|
+
const separator = { type: 'text', text: '此前可见对话结束。以下为当前用户输入:\n' };
|
|
72
|
+
const retained = [];
|
|
73
|
+
// prepareInput guarantees a nonempty current prompt. Each inserted block adds
|
|
74
|
+
// its JSON bytes and one comma; count each round once, not the whole prefix.
|
|
75
|
+
let bytes = Buffer.byteLength(JSON.stringify({ prompt: base.prompt, systemPrompt: base.systemPrompt }), 'utf8') + Buffer.byteLength(JSON.stringify(separator), 'utf8') + 1;
|
|
76
|
+
// Whole consecutive rounds, newest first. The existing byte capacity is the
|
|
77
|
+
// only bound; N is computed from actual encoded text/image sizes, not a cap.
|
|
78
|
+
for (const group of groups.toReversed()) {
|
|
79
|
+
const blocks = [], counts = { textBlocks: 0, imageBlocks: 0, offloadedImagePlaceholders: 0, omittedReasoningBlocks: 0 };
|
|
80
|
+
for (const message of group) {
|
|
81
|
+
options.signal?.throwIfAborted();
|
|
82
|
+
blocks.push({ type: 'text', text: `此前可见对话(历史角色:${message.role};仅为历史记录):\n` });
|
|
83
|
+
for (const block of message.content) {
|
|
84
|
+
if (block.type === 'reasoning') {
|
|
85
|
+
counts.omittedReasoningBlocks++;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (block.type !== 'text' && block.type !== 'image')
|
|
89
|
+
continue;
|
|
90
|
+
blocks.push(await publicBlock(block, options, readImage, true));
|
|
91
|
+
if (block.type === 'text')
|
|
92
|
+
counts.textBlocks++;
|
|
93
|
+
else if (block.offloaded)
|
|
94
|
+
counts.offloadedImagePlaceholders++;
|
|
84
95
|
else
|
|
85
|
-
|
|
96
|
+
counts.imageBlocks++;
|
|
86
97
|
}
|
|
98
|
+
blocks.push({ type: 'text', text: `\n(历史角色:${message.role} 的记录结束)\n` });
|
|
87
99
|
}
|
|
88
|
-
|
|
100
|
+
const additional = Buffer.byteLength(JSON.stringify(blocks), 'utf8') - 1; // Strip [] and add the comma before the retained suffix.
|
|
101
|
+
if (bytes + additional > capacity.maxBytes)
|
|
102
|
+
break;
|
|
103
|
+
bytes += additional;
|
|
104
|
+
retained.push(blocks);
|
|
105
|
+
historyTransfer.retainedRounds++;
|
|
106
|
+
historyTransfer.omittedRounds--;
|
|
107
|
+
for (const key of ['textBlocks', 'imageBlocks', 'offloadedImagePlaceholders', 'omittedReasoningBlocks'])
|
|
108
|
+
historyTransfer[key] += counts[key];
|
|
89
109
|
}
|
|
90
|
-
|
|
91
|
-
return { ...input, prompt, historyTransfer, runtimeSnapshots };
|
|
110
|
+
return { ...base, prompt: retained.length ? [...retained.toReversed().flat(), separator, ...base.prompt] : base.prompt, historyTransfer };
|
|
92
111
|
}
|
|
93
112
|
/** The attachment service supplies verified bytes; client paths never cross SSH. */
|
|
94
113
|
export async function prepareInput(options, readImage) {
|
package/dist/presentation.d.ts
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
export declare const REMOTE_CODEX_NAME = "Codex\uFF08\u8FDC\u7A0B\u4E3B\u673A\uFF09";
|
|
3
3
|
export declare const CONNECTION_REQUIRED = "\u8FDC\u7A0B\u4E3B\u673A\u8FDE\u63A5\u7EC4\u4EF6\u6CA1\u6709\u88C5\u597D\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002";
|
|
4
4
|
/** Employee failures use business language; diagnostic codes remain separately available. */
|
|
5
|
-
export declare function employeeFailure(code: string, brand?: 'codex' | 'claude'): string;
|
|
5
|
+
export declare function employeeFailure(code: string, brand?: 'codex' | 'claude', promptDispatched?: boolean): string;
|
package/dist/presentation.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const REMOTE_CODEX_NAME = 'Codex(远程主机)';
|
|
3
3
|
export const CONNECTION_REQUIRED = '远程主机连接组件没有装好,请联系管理员。';
|
|
4
4
|
/** Employee failures use business language; diagnostic codes remain separately available. */
|
|
5
|
-
export function employeeFailure(code, brand = 'codex') {
|
|
5
|
+
export function employeeFailure(code, brand = 'codex', promptDispatched = true) {
|
|
6
6
|
const messages = {
|
|
7
7
|
PERMISSION_POLICY_REQUIRED: '我需要读取这条对话的权限设置,目前没有读到;本轮未执行,你的原话仍保留。',
|
|
8
8
|
PERMISSION_MODE_UNSUPPORTED: '这个权限档位还没有对应的远程执行能力;我需要主机连接组件支持该档位,本轮未执行,你的原话仍保留。',
|
|
@@ -23,7 +23,7 @@ export function employeeFailure(code, brand = 'codex') {
|
|
|
23
23
|
EMPLOYEE_CONTEXT_CHANGED: '本机文件夹或连接已变化,本轮已停止;恢复后可在原会话继续。',
|
|
24
24
|
EMPLOYEE_WORKSPACE_INVALID: '无法核对这条对话所属的本机文件夹,本轮未执行;请在工作区中重新打开对话。',
|
|
25
25
|
DEPENDENCY_REQUIRED: CONNECTION_REQUIRED,
|
|
26
|
-
MODEL_CATALOG_UNAVAILABLE: '所选型号暂时不可用,请打开模型菜单重新选择后再发送。',
|
|
26
|
+
MODEL_CATALOG_UNAVAILABLE: '所选型号暂时不可用,请打开模型菜单重新选择后再发送。' + (!promptDispatched ? ' 本轮输入未发送。' : ''),
|
|
27
27
|
LOGIN_REQUIRED: '需要登录,请到设置 → 远程主机连接 点登录',
|
|
28
28
|
LOGIN_COMPLETED: '登录已完成,请重新发送本轮内容。',
|
|
29
29
|
LOGIN_FAILED: '登录未完成,请到设置 → 远程主机连接 点登录;如仍有问题,请联系管理员。',
|
|
@@ -41,7 +41,8 @@ export function employeeFailure(code, brand = 'codex') {
|
|
|
41
41
|
HOST_TRUST_REQUIRED: '远程主机连接信息还未准备好,请联系管理员。',
|
|
42
42
|
POLICY_DENIED: '这个账号暂时不能使用,请联系公司账号管理员。',
|
|
43
43
|
SESSION_CONTEXT_MISMATCH: '远程主机连接已改变,请重新开始本次检查。',
|
|
44
|
-
|
|
44
|
+
REMOTE_SESSION_BUSY: '原会话仍被主机上的上一轮占用,' + (promptDispatched ? '本轮请求未能完成' : '本轮输入未发送') + ';请稍后在原会话重新发送。若持续占用,请联系管理员检查上一轮主机会话。',
|
|
45
|
+
ABORTED: promptDispatched ? '本轮已停止。操作可能已部分执行,请先确认文件;恢复连接后可在原会话继续。' : '本轮已停止,本轮输入未发送;恢复连接后可在原会话重新发送。',
|
|
45
46
|
CONFIRMATION_REQUIRED: '请先选择是否打开授权窗口。',
|
|
46
47
|
CONTEXT_UNSUPPORTED: '远程 Codex 暂不支持这类会话内容,请联系管理员。',
|
|
47
48
|
CONTENT_UNSUPPORTED: '远程 Codex 暂不支持这类附件,请联系管理员。',
|
|
@@ -79,6 +80,6 @@ export function employeeFailure(code, brand = 'codex') {
|
|
|
79
80
|
if (code === 'AW_EMPLOYEE_BINARY_MISSING')
|
|
80
81
|
return '本机执行组件没有装齐,本轮没有执行,请重新安装插件。';
|
|
81
82
|
if (code.startsWith('AW_EMPLOYEE_') || code.startsWith('EMPLOYEE_'))
|
|
82
|
-
return '你电脑上的执行连接已中断,本轮已停止;操作可能已部分执行,请先确认文件,恢复后可在原会话继续。';
|
|
83
|
-
return '本轮没有完成。请检查连接,恢复后可在原会话继续;操作可能已部分执行,请先确认文件。';
|
|
83
|
+
return promptDispatched ? '你电脑上的执行连接已中断,本轮已停止;操作可能已部分执行,请先确认文件,恢复后可在原会话继续。' : '你电脑上的执行连接尚未就绪,本轮输入未发送;请检查连接,恢复后可在原会话重新发送。';
|
|
84
|
+
return promptDispatched ? '本轮没有完成。请检查连接,恢复后可在原会话继续;操作可能已部分执行,请先确认文件。' : '本轮输入未发送。请检查连接,恢复后可在原会话继续。';
|
|
84
85
|
}
|