@ai-workbench/remote-agent 0.8.23 → 0.8.24
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 +3 -1
- package/dist/acp.js +1 -1
- package/dist/employee-mcp.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +36 -5
- package/dist/presentation.d.ts +0 -1
- package/dist/presentation.js +0 -1
- package/dist/provider.d.ts +0 -14
- package/dist/provider.js +1 -14
- 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.24 · 插件 → 添加插件
|
|
2
2
|
|
|
3
3
|
通过官方 DSH 插件入口使用 Claude(远程主机)与 Codex(远程主机)。登录和工作区来源由“远程主机连接”组件提供;员工在原生工作区和模型菜单中选择文件夹与型号。
|
|
4
4
|
|
|
@@ -43,3 +43,5 @@ Codex 员工端只使用随包提供的原生组件,通道等待本次组件
|
|
|
43
43
|
工程验证、独立审查、固定包摘要及实际设备验收分别记录在 `docs/evidence/2026-10-24-X-executor-readiness/` 和项目 X 回执中。插件不修改 DSH 核心,不添加启动器或自定义 profile。
|
|
44
44
|
|
|
45
45
|
远程助手参数页只显示官方 ConfigForms 当前值,不提供保存、放弃或恢复继承值;修改请使用 DSH 官方 Config“打开配置文件”入口。
|
|
46
|
+
|
|
47
|
+
模型目录在官方启动读取时获取,并在连接变为 connected 时经官方注册刷新;官方菜单打开或重试读取缓存是 DSH 官方限制,本插件不改官方菜单或核心。真正不支持的推理档位由 DSH 预检,其英文提示保留为观察项。
|
package/dist/acp.js
CHANGED
|
@@ -484,7 +484,7 @@ export class AcpSession {
|
|
|
484
484
|
signal?.addEventListener('abort', abort, { once: true });
|
|
485
485
|
try {
|
|
486
486
|
const hello = await this.stage('acp-initialize', () => this.connection.agent.request(acp.methods.agent.initialize, {
|
|
487
|
-
protocolVersion: acp.PROTOCOL_VERSION, clientInfo: { name: '@ai-workbench/remote-agent', version: '0.8.
|
|
487
|
+
protocolVersion: acp.PROTOCOL_VERSION, clientInfo: { name: '@ai-workbench/remote-agent', version: '0.8.24' },
|
|
488
488
|
clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false, session: { notices: {} }, ...(this.employeeMeta ? { _meta: { awEmployeeExecution: { version: 1, closeReason: 1 } } } : {}) },
|
|
489
489
|
}, { cancellationSignal: signal }));
|
|
490
490
|
if (hello.protocolVersion !== acp.PROTOCOL_VERSION)
|
package/dist/employee-mcp.js
CHANGED
|
@@ -152,7 +152,7 @@ export async function openEmployeeMcp(options) {
|
|
|
152
152
|
return tools.call(request.params.name, request.params.arguments ?? {}, signal, event => { if (sink)
|
|
153
153
|
observeUsing(event, sink); });
|
|
154
154
|
});
|
|
155
|
-
mcp.onerror = () => { observeConnection?.({ layer: 'relay', initiator: 'mcp.server-error', reason: 'EMPLOYEE_MCP_PROTOCOL_OR_TRANSPORT_ERROR', action: 'failure' }); observe({ kind: 'session', severity: 'warning', code: 'CLAUDE_EMPLOYEE_MCP_UNKNOWN', summary: '
|
|
155
|
+
mcp.onerror = () => { observeConnection?.({ layer: 'relay', initiator: 'mcp.server-error', reason: 'EMPLOYEE_MCP_PROTOCOL_OR_TRANSPORT_ERROR', action: 'failure' }); observe({ kind: 'session', severity: 'warning', code: 'CLAUDE_EMPLOYEE_MCP_UNKNOWN', summary: '本机工具连接中断,在途结果未知,没有重放;恢复后可在原会话继续。' }); };
|
|
156
156
|
mcp.onclose = () => { observeConnection?.({ layer: 'relay', initiator: 'mcp.client-closed', reason: 'MCP_CLIENT_CLOSED', action: 'close' }); clients.delete(mcp); transports.delete(transport); };
|
|
157
157
|
void mcp.connect(transport).catch(error => { observeConnection?.({ layer: 'relay', initiator: 'mcp.connect-failure', reason: closeCode(error, 'MCP_CONNECT_FAILED'), action: 'close' }); socket.destroy(); });
|
|
158
158
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -74,8 +74,8 @@ export declare class CodexRemoteAdapter extends LlmAdapter {
|
|
|
74
74
|
listModels(provider: string): Promise<(LlmResolvedModelInfo & {
|
|
75
75
|
catalog: HostModel;
|
|
76
76
|
})[]>;
|
|
77
|
-
resolveModel(provider: string, id: string,
|
|
78
|
-
prepareCall(provider: string, id: string,
|
|
77
|
+
resolveModel(provider: string, id: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
|
|
78
|
+
prepareCall(provider: string, id: string, signal?: AbortSignal): Promise<{
|
|
79
79
|
model: LlmResolvedModelInfo;
|
|
80
80
|
stream: (options: GenerateOptions) => AsyncGenerator<StreamChunk, any, any>;
|
|
81
81
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import { createClaudeLocalProvider } from "./claude-local.js";
|
|
|
27
27
|
import { readLocalUserTurn } from "./local-user-turn.js";
|
|
28
28
|
import { readEmployeeWorkspace } from "./employee-workspace.js";
|
|
29
29
|
import { createPreflightDiagnostics } from "./preflight-diagnostic.js";
|
|
30
|
-
import { installModelInputRetention } from "./model-input-retention.js";
|
|
30
|
+
import { installModelInputRetention, markModelPreparationFailure } from "./model-input-retention.js";
|
|
31
31
|
import { dshPermissionSource, permissionMode } from "./permissions.js";
|
|
32
32
|
export { readDshPermissions } from "./permissions.js";
|
|
33
33
|
export const name = 'ai-workbench-remote-agent';
|
|
@@ -121,8 +121,33 @@ export class CodexRemoteAdapter extends LlmAdapter {
|
|
|
121
121
|
finally {
|
|
122
122
|
catalog.release();
|
|
123
123
|
} }
|
|
124
|
-
async resolveModel(provider, id,
|
|
125
|
-
|
|
124
|
+
async resolveModel(provider, id, signal) {
|
|
125
|
+
const displayed = this.modelPresentation.resolve(provider, id);
|
|
126
|
+
if (displayed)
|
|
127
|
+
return displayed;
|
|
128
|
+
const active = signal ? AbortSignal.any([signal, this.lifetime.signal]) : this.lifetime.signal;
|
|
129
|
+
const catalog = await this.catalog(active);
|
|
130
|
+
try {
|
|
131
|
+
active.throwIfAborted();
|
|
132
|
+
this.modelPresentation.remember(catalog);
|
|
133
|
+
const resolved = this.modelPresentation.resolve(provider, id);
|
|
134
|
+
if (!resolved)
|
|
135
|
+
throw new LlmError('所选模型当前不可用,请打开模型菜单重新选择。', 'MODEL_CATALOG_UNAVAILABLE');
|
|
136
|
+
return resolved;
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
catalog.release();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async prepareCall(provider, id, signal) {
|
|
143
|
+
try {
|
|
144
|
+
return { model: await this.resolveModel(provider, id, signal), stream: (options) => this.stream(options) };
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
markModelPreparationFailure(provider, error, signal);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
126
151
|
providerRetryPolicy() { return { mode: 'normal', maxRetries: 0, retryableCodes: [], initialDelayMs: 0, maxDelayMs: 0, jitterRatio: 0 }; }
|
|
127
152
|
cleanupRuntime(runtime, cause = { layer: 'adapter', initiator: 'adapter.cleanup-runtime', reason: 'RUNTIME_CLEANUP', action: 'dispose' }) {
|
|
128
153
|
runtime.closeDiagnostics?.record(cause);
|
|
@@ -665,12 +690,18 @@ export function apply(ctx, live) {
|
|
|
665
690
|
}
|
|
666
691
|
return managerForProfile().recordLoginFailure({ sessionId, code, diagnostic, context: { turn, step } });
|
|
667
692
|
}, modelDirectory, preflightDiagnostics, dshPermissionSource(ctx));
|
|
668
|
-
for (const agent of AGENTS)
|
|
669
|
-
void adapter.listModels(agent.id).catch(() => ctx.logger('remote-agent').warn('模型列表暂不可用,打开菜单时可重新读取'));
|
|
670
693
|
const ids = AGENTS.map(agent => agent.id);
|
|
671
694
|
const entries = () => AGENTS.map(agent => ({ provider: agent.id, displayName: agent.name[language], settingsNs: actualSettingsNamespace ?? settingsNamespace, settingsPath: [] }));
|
|
672
695
|
const directory = ctx.llm.registerConfigurableProviders(entries());
|
|
673
696
|
const registration = ctx.llm.registerAdapter(ids, adapter);
|
|
697
|
+
let connection;
|
|
698
|
+
ctx.on('ai-workbench/connection-state', state => {
|
|
699
|
+
const previous = connection;
|
|
700
|
+
connection = state;
|
|
701
|
+
// Official replacement invalidates the browser's shared catalog and loads it.
|
|
702
|
+
if (state.phase === 'connected' && (previous?.phase !== 'connected' || previous.instanceId !== state.instanceId || previous.epoch !== state.epoch))
|
|
703
|
+
registration.replace(ids);
|
|
704
|
+
});
|
|
674
705
|
installModelInputRetention(ctx, { isOurProvider: provider => ids.includes(provider), diagnosticForAttempt: position => preflightDiagnostics.forPreparation(position.sessionId, position), preflightDiagnostic: (provider, message) => diagnostic('preflight', provider, message), diagnostic: (provider, message) => diagnostic('input', provider, message) });
|
|
675
706
|
const cleanup = async (id) => { try {
|
|
676
707
|
await adapter.detachSession(id);
|
package/dist/presentation.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/** Functional wording from connect-api appendix D1-D3 (L0.5.1 candidate). */
|
|
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
|
-
export declare const TEST_HOST_NOTICE = "\u8FDC\u7A0B\u4E3B\u673A\u6B63\u5728\u4F7F\u7528\u6D4B\u8BD5\u914D\u7F6E\uFF0C\u9047\u5230\u95EE\u9898\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002";
|
|
5
4
|
/** Employee failures use business language; diagnostic codes remain separately available. */
|
|
6
5
|
export declare function employeeFailure(code: string, brand?: 'codex' | 'claude'): string;
|
package/dist/presentation.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/** Functional wording from connect-api appendix D1-D3 (L0.5.1 candidate). */
|
|
2
2
|
export const REMOTE_CODEX_NAME = 'Codex(远程主机)';
|
|
3
3
|
export const CONNECTION_REQUIRED = '远程主机连接组件没有装好,请联系管理员。';
|
|
4
|
-
export const TEST_HOST_NOTICE = '远程主机正在使用测试配置,遇到问题请联系管理员。';
|
|
5
4
|
/** Employee failures use business language; diagnostic codes remain separately available. */
|
|
6
5
|
export function employeeFailure(code, brand = 'codex') {
|
|
7
6
|
const messages = {
|
package/dist/provider.d.ts
CHANGED
|
@@ -89,18 +89,6 @@ export type RuntimeProvider = ((request: RuntimeRequest) => Promise<Runtime>) &
|
|
|
89
89
|
preflight?: (request: RuntimeRequest) => Promise<void>;
|
|
90
90
|
};
|
|
91
91
|
export interface ConnectTarget {
|
|
92
|
-
hostContext?: {
|
|
93
|
-
enforcement: 'production' | 'test';
|
|
94
|
-
checkExitCode: 0 | 1;
|
|
95
|
-
failedChecks: {
|
|
96
|
-
id: string;
|
|
97
|
-
status: string;
|
|
98
|
-
}[];
|
|
99
|
-
unverifiedChecks: {
|
|
100
|
-
id: string;
|
|
101
|
-
status: string;
|
|
102
|
-
}[];
|
|
103
|
-
};
|
|
104
92
|
host: string;
|
|
105
93
|
username: string;
|
|
106
94
|
port: number;
|
|
@@ -165,8 +153,6 @@ declare module '@deepseek-ai/cordis' {
|
|
|
165
153
|
export declare function awaitL<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
166
154
|
export declare function unwrap<T>(result: Result<T>): T;
|
|
167
155
|
export declare function validateTarget(t: ConnectTarget): void;
|
|
168
|
-
/** Only the declared public check identifiers/statuses, never provider evidence. */
|
|
169
|
-
export declare function hostContextNotice(t: ConnectTarget): string | undefined;
|
|
170
156
|
export declare function identity(t: ConnectTarget): string;
|
|
171
157
|
/** Reject draft.3 and legacy runtime rather than inventing workspace bindings. */
|
|
172
158
|
export declare function requireNativeWorkspace(api: ConnectApi): asserts api is ConnectApi & NativeWorkspaceApi;
|
package/dist/provider.js
CHANGED
|
@@ -2,7 +2,7 @@ import { hostWorkspaceGuard } from "./host-workspace.js";
|
|
|
2
2
|
import { connectNeedError } from "./connect-need.js";
|
|
3
3
|
import { loginDiagnostic, loginReason } from "./login-diagnostic.js";
|
|
4
4
|
import { NeedError } from "./remote.js";
|
|
5
|
-
import { CONNECTION_REQUIRED
|
|
5
|
+
import { CONNECTION_REQUIRED } from "./presentation.js";
|
|
6
6
|
import { CODEX_AGENT } from "./agents.js";
|
|
7
7
|
export function requireLoginCoordinator(api) {
|
|
8
8
|
if (!['getConnectionState', 'getLoginPromptState', 'requestLoginPrompt', 'refreshLoginPrompts'].every(key => typeof api[key] === 'function'))
|
|
@@ -118,19 +118,6 @@ export function validateTarget(t) {
|
|
|
118
118
|
|| ![t.projectRoot, t.session.command, t.session.root, t.session.settingsPath].every(p => typeof p === 'string' && p.startsWith('/'))) {
|
|
119
119
|
throw new NeedError('CONNECT_API_MISMATCH', '我需要 connect-api 0.3.0 的可信主机、项目和 session 能力;旧目标不能继续使用', 'L 提供的完整 0.3.0 目标');
|
|
120
120
|
}
|
|
121
|
-
hostContextNotice(t);
|
|
122
|
-
}
|
|
123
|
-
/** Only the declared public check identifiers/statuses, never provider evidence. */
|
|
124
|
-
export function hostContextNotice(t) {
|
|
125
|
-
const h = t.hostContext;
|
|
126
|
-
if (h === undefined)
|
|
127
|
-
return;
|
|
128
|
-
const checks = (items) => Array.isArray(items) && items.every(item => item && typeof item.id === 'string' && typeof item.status === 'string');
|
|
129
|
-
if (!h || (h.enforcement !== 'test' && h.enforcement !== 'production') || (h.checkExitCode !== 0 && h.checkExitCode !== 1) || !checks(h.failedChecks) || !checks(h.unverifiedChecks))
|
|
130
|
-
throw new NeedError('CONNECT_API_MISMATCH', '主机检查背景无效,不能假定已通过生产检查', 'L 提供的有效 hostContext');
|
|
131
|
-
if (h.enforcement !== 'test')
|
|
132
|
-
return;
|
|
133
|
-
return TEST_HOST_NOTICE;
|
|
134
121
|
}
|
|
135
122
|
export function identity(t) { return `${t.username}@${t.host}:${t.port}`; }
|
|
136
123
|
/** Reject draft.3 and legacy runtime rather than inventing workspace bindings. */
|