@ai-workbench/remote-agent 0.8.21 → 0.8.23

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.
Files changed (95) hide show
  1. package/README.md +27 -156
  2. package/dist/acp.d.ts +20 -15
  3. package/dist/acp.js +197 -224
  4. package/dist/agents.d.ts +0 -1
  5. package/dist/agents.js +2 -2
  6. package/dist/broker-runtime.d.ts +3 -5
  7. package/dist/broker-runtime.js +45 -342
  8. package/dist/broker.d.ts +6 -31
  9. package/dist/broker.js +42 -113
  10. package/dist/catalog-ssh.d.ts +2 -31
  11. package/dist/catalog-ssh.js +9 -39
  12. package/dist/claude-local.d.ts +1 -1
  13. package/dist/claude-local.js +40 -105
  14. package/dist/client.js +34 -127
  15. package/dist/close-diagnostics.d.ts +6 -20
  16. package/dist/close-diagnostics.js +13 -57
  17. package/dist/connect-contract.d.ts +4 -8
  18. package/dist/conversation-details.d.ts +0 -29
  19. package/dist/conversation-details.js +8 -99
  20. package/dist/employee-endpoint.d.ts +1 -3
  21. package/dist/employee-endpoint.js +8 -39
  22. package/dist/employee-exec.d.ts +4 -3
  23. package/dist/employee-exec.js +25 -13
  24. package/dist/employee-info.d.ts +5 -1
  25. package/dist/employee-info.js +16 -5
  26. package/dist/employee-location.js +3 -4
  27. package/dist/employee-mcp.js +44 -69
  28. package/dist/employee-native.d.ts +1 -3
  29. package/dist/employee-native.js +6 -27
  30. package/dist/employee-presentation.d.ts +0 -5
  31. package/dist/employee-presentation.js +0 -15
  32. package/dist/employee-provider.d.ts +3 -11
  33. package/dist/employee-provider.js +69 -205
  34. package/dist/employee-reasons.js +1 -5
  35. package/dist/employee-shell.d.ts +2 -1
  36. package/dist/employee-shell.js +10 -13
  37. package/dist/employee-ssh.d.ts +1 -3
  38. package/dist/employee-ssh.js +13 -16
  39. package/dist/employee-tools.d.ts +5 -5
  40. package/dist/failure-evidence.d.ts +2 -10
  41. package/dist/failure-evidence.js +12 -61
  42. package/dist/host-workspace.d.ts +4 -2
  43. package/dist/host-workspace.js +1 -1
  44. package/dist/index.d.ts +13 -43
  45. package/dist/index.js +190 -489
  46. package/dist/input.js +2 -3
  47. package/dist/local-user-turn.js +5 -6
  48. package/dist/mapping.d.ts +0 -3
  49. package/dist/mapping.js +0 -34
  50. package/dist/model-catalog.d.ts +2 -41
  51. package/dist/model-catalog.js +24 -282
  52. package/dist/model-configuration.d.ts +0 -3
  53. package/dist/model-configuration.js +8 -47
  54. package/dist/model-presentation.d.ts +1 -0
  55. package/dist/model-presentation.js +2 -2
  56. package/dist/permissions.d.ts +15 -0
  57. package/dist/permissions.js +30 -0
  58. package/dist/preflight-diagnostic.js +11 -22
  59. package/dist/preflight-payload.d.ts +1 -1
  60. package/dist/preflight-payload.js +2 -2
  61. package/dist/presentation.js +21 -41
  62. package/dist/provider.d.ts +12 -34
  63. package/dist/provider.js +17 -92
  64. package/dist/readiness.js +1 -7
  65. package/dist/remote-details.d.ts +41 -17
  66. package/dist/remote-details.js +84 -381
  67. package/dist/workspace-source.d.ts +1 -25
  68. package/dist/workspace-source.js +1 -138
  69. package/package.json +11 -12
  70. package/dist/catalog-diagnostics.d.ts +0 -16
  71. package/dist/catalog-diagnostics.js +0 -108
  72. package/dist/host-layout.d.ts +0 -8
  73. package/dist/host-layout.js +0 -9
  74. package/dist/job.d.ts +0 -17
  75. package/dist/job.js +0 -57
  76. package/dist/model-defaults.d.ts +0 -29
  77. package/dist/model-defaults.js +0 -62
  78. package/dist/oneshot.d.ts +0 -13
  79. package/dist/oneshot.js +0 -78
  80. package/dist/protocol-boundary.d.ts +0 -13
  81. package/dist/protocol-boundary.js +0 -49
  82. package/dist/provider-locale.d.ts +0 -19
  83. package/dist/provider-locale.js +0 -73
  84. package/dist/recovery-checkpoint.d.ts +0 -6
  85. package/dist/recovery-checkpoint.js +0 -71
  86. package/dist/recovery.d.ts +0 -51
  87. package/dist/recovery.js +0 -61
  88. package/dist/sdk-ssh-wrapper.d.ts +0 -2
  89. package/dist/sdk-ssh-wrapper.js +0 -34
  90. package/dist/stage-timing.d.ts +0 -31
  91. package/dist/stage-timing.js +0 -61
  92. package/dist/workspace-notice.d.ts +0 -47
  93. package/dist/workspace-notice.js +0 -273
  94. package/dist/workspace-source-confirmation.d.ts +0 -4
  95. package/dist/workspace-source-confirmation.js +0 -12
@@ -36,11 +36,11 @@ export class EmployeeSocketTransport {
36
36
  this.maxBytes = maxBytes;
37
37
  this.observeClose = observeClose;
38
38
  }
39
- failed(error) { try {
39
+ failed(error) { this.failure ??= error; try {
40
40
  this.onerror?.(error);
41
41
  }
42
- catch (observation) {
43
- this.failure = observation instanceof Error ? observation : new Error('EMPLOYEE_MCP_OBSERVATION_FAILED');
42
+ catch {
43
+ console.warn('EMPLOYEE_MCP_DIAGNOSTIC_DROPPED');
44
44
  }
45
45
  finally {
46
46
  void this.close({ layer: 'relay', initiator: 'mcp.socket-failure', reason: closeCode(error, 'EMPLOYEE_MCP_PROTOCOL_OR_SOCKET_ERROR'), action: 'failure' });
@@ -79,8 +79,18 @@ export class EmployeeSocketTransport {
79
79
  }
80
80
  await new Promise((yes, no) => this.socket.write(wire, error => error ? no(error) : yes()));
81
81
  }
82
- async close(cause = { layer: 'relay', initiator: 'mcp.transport-close', reason: 'MCP_TRANSPORT_CLOSED', action: 'close' }) { this.observeClose?.({ ...cause, changes: cause.changes ?? [{ field: 'mcp.ended', before: this.ended, after: true }] }); if (this.ended)
83
- return; this.ended = true; this.lifetime.abort(); this.socket.destroy(); this.onclose?.(); }
82
+ async close(cause = { layer: 'relay', initiator: 'mcp.transport-close', reason: 'MCP_TRANSPORT_CLOSED', action: 'close' }) { try {
83
+ this.observeClose?.({ ...cause, changes: cause.changes ?? [{ field: 'mcp.ended', before: this.ended, after: true }] });
84
+ }
85
+ catch {
86
+ console.warn('EMPLOYEE_MCP_DIAGNOSTIC_DROPPED');
87
+ } if (this.ended)
88
+ return; this.ended = true; this.lifetime.abort(); this.socket.destroy(); try {
89
+ this.onclose?.();
90
+ }
91
+ catch {
92
+ console.warn('EMPLOYEE_MCP_CLOSE_OBSERVER_FAILED');
93
+ } }
84
94
  }
85
95
  export async function openEmployeeMcp(options) {
86
96
  if (process.platform !== 'darwin')
@@ -88,7 +98,7 @@ export async function openEmployeeMcp(options) {
88
98
  if (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 1)
89
99
  throw new NeedError('SETTINGS_REQUIRED', '本机工具消息容量无效。', 'acpMaxMessageBytes');
90
100
  await access('/usr/bin/nc', constants.X_OK);
91
- const tools = createEmployeeTools({ closeDiagnostics: options.closeDiagnostics, cwd: options.lease.target.local.directory.path, shell: options.lease.target.endpoint.endpointShell, uid: options.lease.target.endpoint.remoteUid, maxBytes: options.maxBytes, killGraceMs: options.killGraceMs, detail: observe, runShell: options.runShell, validate: signal => options.lease.validateDirectory(signal).then(() => { }) });
101
+ const tools = createEmployeeTools({ closeDiagnostics: options.closeDiagnostics, cwd: options.lease.target.local.directory.path, shell: options.lease.target.endpoint.endpointShell, uid: options.lease.target.endpoint.remoteUid, maxBytes: options.maxBytes, killGraceMs: options.killGraceMs, detail: observe, runShell: options.runShell, validate: async (signal) => { signal?.throwIfAborted(); options.lease.signal.throwIfAborted(); } });
92
102
  const root = await mkdtemp('/private/tmp/aw-x87-'), socketPath = root + '/mcp';
93
103
  try {
94
104
  const info = await lstat(root);
@@ -97,51 +107,27 @@ export async function openEmployeeMcp(options) {
97
107
  }
98
108
  catch (error) {
99
109
  options.closeDiagnostics?.record({ layer: 'relay', initiator: 'mcp.storage-failure', reason: closeCode(error), action: 'failure' });
100
- const failures = [error];
101
- try {
102
- await tools.close({ layer: 'executor', initiator: 'mcp.storage-cleanup', reason: 'MCP_STORAGE_FAILED', action: 'close' });
103
- }
104
- catch (cleanup) {
105
- failures.push(cleanup);
106
- }
107
- try {
108
- await rm(root, { recursive: true });
109
- }
110
- catch (cleanup) {
111
- failures.push(cleanup);
112
- }
113
- try {
114
- options.closeDiagnostics?.assertRecorded();
115
- }
116
- catch (reporting) {
117
- failures.push(reporting);
110
+ for (const clean of [() => tools.close({ layer: 'executor', initiator: 'mcp.storage-cleanup', reason: 'MCP_STORAGE_FAILED', action: 'close' }), () => rm(root, { recursive: true })]) {
111
+ try {
112
+ await clean();
113
+ }
114
+ catch {
115
+ console.warn('EMPLOYEE_MCP_CLEANUP_FAILED');
116
+ }
118
117
  }
119
- if (failures.length > 1)
120
- throw new AggregateError(failures, 'EMPLOYEE_MCP_STORAGE_AND_CLEANUP_FAILED');
121
118
  throw error;
122
119
  }
123
120
  const clients = new Set(), transports = new Set();
124
- let closing, diagnosticFailure;
125
- const failureLifetime = new AbortController();
126
- const poison = (error) => {
127
- options.closeDiagnostics?.record({ layer: 'relay', initiator: 'mcp.poison', reason: closeCode(error, 'CONVERSATION_DETAILS_FAILED'), action: 'invalidate' });
128
- diagnosticFailure ??= error;
129
- failureLifetime.abort(error);
130
- // Close is memoized synchronously: no fresh connection/call can pass the fence.
131
- void options.lease.close({ layer: 'endpoint', initiator: 'mcp.poison-lease', reason: 'CONVERSATION_DETAILS_FAILED', action: 'close' }).catch(failure => { diagnosticFailure ??= failure; });
132
- void close({ layer: 'relay', initiator: 'mcp.poison-close', reason: 'CONVERSATION_DETAILS_FAILED', action: 'close' }).catch(failure => { diagnosticFailure ??= failure; });
133
- };
134
- function observeUsing(event, sink) { if (diagnosticFailure)
135
- throw diagnosticFailure; try {
121
+ let closing;
122
+ function observeUsing(event, sink) { try {
136
123
  sink(event);
137
124
  }
138
- catch (error) {
139
- poison(error);
140
- throw error;
125
+ catch {
126
+ console.warn('EMPLOYEE_MCP_DIAGNOSTIC_DROPPED');
141
127
  } }
142
128
  function observe(event) { observeUsing(event, options.detail); }
143
129
  const server = createServer(socket => {
144
- if (closing || failureLifetime.signal.aborted || options.lease.signal.aborted) {
130
+ if (closing || options.lease.signal.aborted) {
145
131
  options.closeDiagnostics?.record({ layer: 'relay', initiator: 'mcp.reject-late-socket', reason: 'MCP_CLOSING', action: 'close' });
146
132
  socket.destroy();
147
133
  return;
@@ -155,16 +141,18 @@ export async function openEmployeeMcp(options) {
155
141
  const active = options.activeSignal();
156
142
  if (!active || active.aborted)
157
143
  return { isError: true, content: [{ type: 'text', text: 'EMPLOYEE_NO_ACTIVE_TURN:当前没有已接纳的用户轮次,本机工具未执行。' }] };
158
- const signal = AbortSignal.any([active, extra.signal, transport.signal, options.lease.signal, failureLifetime.signal]);
159
- const sink = options.captureDetail?.() ?? options.detail;
160
- return tools.call(request.params.name, request.params.arguments ?? {}, signal, event => observeUsing(event, sink));
144
+ const signal = AbortSignal.any([active, extra.signal, transport.signal, options.lease.signal]);
145
+ let sink;
146
+ try {
147
+ sink = options.captureDetail?.() ?? options.detail;
148
+ }
149
+ catch {
150
+ console.warn('EMPLOYEE_MCP_DIAGNOSTIC_DROPPED');
151
+ }
152
+ return tools.call(request.params.name, request.params.arguments ?? {}, signal, event => { if (sink)
153
+ observeUsing(event, sink); });
161
154
  });
162
- mcp.onerror = () => { observeConnection?.({ layer: 'relay', initiator: 'mcp.server-error', reason: 'EMPLOYEE_MCP_PROTOCOL_OR_TRANSPORT_ERROR', action: 'failure' }); try {
163
- observe({ kind: 'session', severity: 'warning', code: 'CLAUDE_EMPLOYEE_MCP_UNKNOWN', summary: '本机工具连接出现协议或传输错误;在途结果未知,没有重放' });
164
- }
165
- catch (error) {
166
- poison(error);
167
- } };
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: '本机工具连接出现协议或传输错误;恢复后可在原会话继续。' }); };
168
156
  mcp.onclose = () => { observeConnection?.({ layer: 'relay', initiator: 'mcp.client-closed', reason: 'MCP_CLIENT_CLOSED', action: 'close' }); clients.delete(mcp); transports.delete(transport); };
169
157
  void mcp.connect(transport).catch(error => { observeConnection?.({ layer: 'relay', initiator: 'mcp.connect-failure', reason: closeCode(error, 'MCP_CONNECT_FAILED'), action: 'close' }); socket.destroy(); });
170
158
  });
@@ -172,12 +160,11 @@ export async function openEmployeeMcp(options) {
172
160
  options.closeDiagnostics?.record({ ...cause, changes: cause.changes ?? [{ field: 'mcp.closing', before: !!closing, after: true }] });
173
161
  return closing ??= Promise.resolve().then(async () => {
174
162
  options.lease.signal.removeEventListener('abort', aborted);
175
- const errors = [], clean = async (operation) => { try {
163
+ const clean = async (operation) => { try {
176
164
  await operation();
177
165
  }
178
- catch (error) {
179
- if (!errors.includes(error))
180
- errors.push(error);
166
+ catch {
167
+ console.warn('EMPLOYEE_MCP_CLEANUP_FAILED');
181
168
  } };
182
169
  for (const transport of transports)
183
170
  await clean(() => transport.close({ layer: 'relay', initiator: 'mcp.cleanup-transport', reason: 'MCP_CLEANUP', action: 'close' }));
@@ -188,27 +175,15 @@ export async function openEmployeeMcp(options) {
188
175
  if (server.listening)
189
176
  await clean(() => new Promise((yes, no) => server.close(error => error ? no(error) : yes())));
190
177
  await clean(() => rm(root, { recursive: true }));
191
- if (diagnosticFailure && !errors.includes(diagnosticFailure))
192
- errors.unshift(diagnosticFailure);
193
- try {
194
- options.closeDiagnostics?.assertRecorded();
195
- }
196
- catch (error) {
197
- errors.push(error);
198
- }
199
- if (errors.length === 1)
200
- throw errors[0];
201
- if (errors.length)
202
- throw new AggregateError(errors, 'EMPLOYEE_MCP_CLEANUP_FAILED');
203
178
  });
204
179
  };
205
- const aborted = () => { void close({ layer: 'endpoint', initiator: 'mcp.lease-abort', reason: closeCode(options.lease.signal.reason, 'EMPLOYEE_CONTEXT_CHANGED'), action: 'abort' }).catch(error => { diagnosticFailure ??= error; failureLifetime.abort(error); }); };
180
+ const aborted = () => { void close({ layer: 'endpoint', initiator: 'mcp.lease-abort', reason: closeCode(options.lease.signal.reason, 'EMPLOYEE_CONTEXT_CHANGED'), action: 'abort' }).catch(() => console.warn('EMPLOYEE_MCP_CLEANUP_FAILED')); };
206
181
  try {
207
182
  await new Promise((yes, no) => { server.once('error', no); server.listen(socketPath, () => { server.removeListener('error', no); yes(); }); });
208
183
  options.lease.signal.addEventListener('abort', aborted, { once: true });
209
184
  if (options.lease.signal.aborted)
210
185
  throw options.lease.signal.reason;
211
- return { routing: employeeRouting(options.lease.target, socketPath, options.maxBytes), signal: failureLifetime.signal, close };
186
+ return { routing: employeeRouting(options.lease.target, socketPath, options.maxBytes), signal: options.lease.signal, close };
212
187
  }
213
188
  catch (error) {
214
189
  await close({ layer: 'relay', initiator: 'mcp.open-failure', reason: closeCode(error, 'MCP_OPEN_FAILED'), action: 'failure' });
@@ -1,4 +1,3 @@
1
- /** Fixed native input already proven by D18/D20; never resolve a PATH executable. */
2
1
  export declare const EMPLOYEE_NATIVE: Readonly<{
3
2
  version: "0.160.1";
4
3
  platform: "darwin";
@@ -6,13 +5,12 @@ export declare const EMPLOYEE_NATIVE: Readonly<{
6
5
  package: "@openai/codex-darwin-arm64";
7
6
  packageVersion: "0.160.1-darwin-arm64";
8
7
  triple: "aarch64-apple-darwin";
9
- sha256: "09fa44fdc37a5fc70dc1ace31235f90468a2e193d0e85f7552eab068ea2582be";
10
8
  }>;
9
+ /** Resolve the installed executable; no per-turn hash or version probe. */
11
10
  export declare function resolveEmployeeNative(ports?: {
12
11
  platform?: string;
13
12
  arch?: string;
14
13
  resolve?: (name: string) => string;
15
14
  }): Promise<{
16
15
  path: string;
17
- sha256: string;
18
16
  }>;
@@ -1,38 +1,17 @@
1
1
  import { createRequire } from 'node:module';
2
- import { readFile, lstat, realpath, access } from 'node:fs/promises';
3
- import { constants } from 'node:fs';
4
2
  import { dirname, join } from 'node:path';
5
- import { createHash } from 'node:crypto';
6
3
  import { NeedError } from "./remote.js";
7
4
  const require = createRequire(import.meta.url);
8
- /** Fixed native input already proven by D18/D20; never resolve a PATH executable. */
9
- export const EMPLOYEE_NATIVE = Object.freeze({ version: '0.160.1', platform: 'darwin', arch: 'arm64', package: '@openai/codex-darwin-arm64', packageVersion: '0.160.1-darwin-arm64', triple: 'aarch64-apple-darwin', sha256: '09fa44fdc37a5fc70dc1ace31235f90468a2e193d0e85f7552eab068ea2582be' });
5
+ export const EMPLOYEE_NATIVE = Object.freeze({ version: '0.160.1', platform: 'darwin', arch: 'arm64', package: '@openai/codex-darwin-arm64', packageVersion: '0.160.1-darwin-arm64', triple: 'aarch64-apple-darwin' });
6
+ /** Resolve the installed executable; no per-turn hash or version probe. */
10
7
  export async function resolveEmployeeNative(ports = {}) {
11
8
  if ((ports.platform ?? process.platform) !== EMPLOYEE_NATIVE.platform || (ports.arch ?? process.arch) !== EMPLOYEE_NATIVE.arch)
12
- throw new NeedError('EMPLOYEE_PLATFORM_UNSUPPORTED', '当前版本的Codex本机执行仅验证了Apple芯片Mac,本轮没有执行。', '对应平台固定执行器及验证');
13
- let manifest;
9
+ throw new NeedError('EMPLOYEE_PLATFORM_UNSUPPORTED', '当前设备尚未支持本机执行。', '对应平台执行器');
14
10
  try {
15
- manifest = (ports.resolve ?? require.resolve)(EMPLOYEE_NATIVE.package + '/package.json');
11
+ const manifest = (ports.resolve ?? require.resolve)(EMPLOYEE_NATIVE.package + '/package.json');
12
+ return { path: join(dirname(manifest), 'vendor', EMPLOYEE_NATIVE.triple, 'bin', 'codex') };
16
13
  }
17
14
  catch {
18
- throw new NeedError('AW_EMPLOYEE_BINARY_MISSING', 'Codex本机执行组件没有装齐,本轮没有执行,请联系管理员。', '随插件安装的固定Codex0.160.1执行组件');
19
- }
20
- try {
21
- const metadata = JSON.parse(await readFile(manifest, 'utf8'));
22
- if (metadata.version !== EMPLOYEE_NATIVE.packageVersion)
23
- throw new NeedError('AW_EMPLOYEE_BINARY_VERSION', 'Codex本机执行组件版本不匹配,本轮没有执行。', '固定Codex0.160.1组件');
24
- const path = join(dirname(manifest), 'vendor', EMPLOYEE_NATIVE.triple, 'bin', 'codex');
25
- const info = await lstat(path);
26
- if (!info.isFile() || info.isSymbolicLink() || await realpath(path) !== path)
27
- throw new NeedError('AW_EMPLOYEE_BINARY_INVALID', 'Codex本机执行组件位置无效,本轮没有执行。', '安装包内的固定原生执行器');
28
- await access(path, constants.X_OK);
29
- if (createHash('sha256').update(await readFile(path)).digest('hex') !== EMPLOYEE_NATIVE.sha256)
30
- throw new NeedError('AW_EMPLOYEE_BINARY_HASH', 'Codex本机执行组件校验不一致,本轮没有执行。', '固定原生执行器SHA256');
31
- return { path, sha256: EMPLOYEE_NATIVE.sha256 };
32
- }
33
- catch (error) {
34
- if (error instanceof NeedError)
35
- throw error;
36
- throw new NeedError('AW_EMPLOYEE_BINARY_INVALID', 'Codex本机执行组件无法核验,本轮没有执行。', '完整安装包与固定执行器');
15
+ throw new NeedError('AW_EMPLOYEE_BINARY_MISSING', '本机执行组件没有装齐,请重新安装插件。', '随插件安装的执行组件');
37
16
  }
38
17
  }
@@ -1,6 +1 @@
1
- import type { GenerateOptions } from '@deepseek-ai/dsh-llm';
2
- export declare const CLAUDE_EMPLOYEE_SCOPE_NOTICE = "\u672C\u8F6E\u516D\u7C7B\u6587\u4EF6\u4E0E\u547D\u4EE4\u5DE5\u5177\u5728\u4F60\u7684\u7535\u8111\u6267\u884C\uFF0C\u4F7F\u7528\u4F60\u9009\u62E9\u7684\u6587\u4EF6\u5939\uFF1BGit\u4E5F\u4F7F\u7528\u672C\u673A\u4ED3\u5E93\u3002\u5B50\u4EE3\u7406\u548C\u5185\u90E8\u76F4\u63A5\u8C03\u7528\u5C1A\u4E0D\u652F\u6301\u672C\u673A\uFF0C\u53EF\u80FD\u4ECD\u5728\u4E3B\u673A\uFF1B\u5DF2\u8BC6\u522B\u7684\u6B64\u7C7B\u5BA1\u6279\u4E0D\u4F1A\u6267\u884C\u3002PDF\u7B49\u4E8C\u8FDB\u5236\u8BFB\u53D6\u3001\u540E\u53F0\u547D\u4EE4\u6682\u4E0D\u652F\u6301\u3002";
3
- export declare const CODEX_EMPLOYEE_SCOPE_NOTICE = "\u6587\u4EF6\u4E0E\u547D\u4EE4\u5728\u672C\u673A\u9009\u5B9A\u76EE\u5F55\u8FD0\u884C\uFF0CGit \u4F7F\u7528\u672C\u673A\u4ED3\u5E93\uFF1B\u6A21\u578B\u3001\u767B\u5F55\u548C\u5168\u5C40\u52A9\u624B\u8981\u6C42\u4ECD\u5728\u8FDC\u7A0B\u4E3B\u673A\u3002\u672C\u673A\u81EA\u5B9A\u4E49\u7684\u9644\u52A0\u5DE5\u5177\u3001\u81EA\u52A8\u52A8\u4F5C\u3001\u63D2\u4EF6\u53CA\u65AD\u5F00\u540E\u7684\u4F1A\u8BDD\u6062\u590D\u6682\u4E0D\u652F\u6301\u3002\u5B50\u4EFB\u52A1\u88AB\u7CFB\u7EDF\u56DE\u6536\u540E\u80FD\u5426\u7EE7\u7EED\uFF0C\u5C1A\u672A\u9A8C\u8BC1\u3002";
4
1
  export declare const EMPLOYEE_EXECUTION_NOTICE = "\u6587\u4EF6\u548C\u547D\u4EE4\u5728\u4F60\u7684\u7535\u8111\u4E0A\u6267\u884C";
5
- /** Presentation receipt only; it grants no process, workspace or replay authority. */
6
- export declare function employeeNoticePreviouslyShown(options: Pick<GenerateOptions, 'messages' | 'sessionId'>): boolean;
@@ -1,16 +1 @@
1
- import { AGENTS } from "./agents.js";
2
- export const CLAUDE_EMPLOYEE_SCOPE_NOTICE = '本轮六类文件与命令工具在你的电脑执行,使用你选择的文件夹;Git也使用本机仓库。子代理和内部直接调用尚不支持本机,可能仍在主机;已识别的此类审批不会执行。PDF等二进制读取、后台命令暂不支持。';
3
- export const CODEX_EMPLOYEE_SCOPE_NOTICE = '文件与命令在本机选定目录运行,Git 使用本机仓库;模型、登录和全局助手要求仍在远程主机。本机自定义的附加工具、自动动作、插件及断开后的会话恢复暂不支持。子任务被系统回收后能否继续,尚未验证。';
4
1
  export const EMPLOYEE_EXECUTION_NOTICE = '文件和命令在你的电脑上执行';
5
- /** Presentation receipt only; it grants no process, workspace or replay authority. */
6
- export function employeeNoticePreviouslyShown(options) {
7
- if (!options.sessionId)
8
- return false;
9
- return options.messages.some(message => {
10
- if (message.role !== 'assistant' || !AGENTS.some(agent => agent.id === message.source.provider))
11
- return false;
12
- const pointer = message.source.replayState?.response;
13
- const sameSession = !!pointer && pointer.version === 2 && pointer.agent === message.source.provider && pointer.dshSessionId === options.sessionId && [pointer.identity, pointer.cwd, pointer.sessionId].every(value => typeof value === 'string' && value.length > 0);
14
- return sameSession && (pointer.presentation?.employeeExecutionNotice === 'local-v1' || message.content.some(block => block.type === 'text' && [CLAUDE_EMPLOYEE_SCOPE_NOTICE, CODEX_EMPLOYEE_SCOPE_NOTICE].some(notice => block.text.startsWith(notice + '\n\n'))));
15
- });
16
- }
@@ -3,12 +3,8 @@ import type { AgentDefinition } from './agents.ts';
3
3
  import type { ConnectApi, ConnectTarget, ConnectionState, Project, Runtime, RuntimeRequest } from './provider.ts';
4
4
  import { type BrokerIo, type SshArgv } from './broker.ts';
5
5
  import type { DetailChannel } from './remote-details.ts';
6
- import type { LocalUserTurnAcceptance } from '@ai-workbench/connect/api';
6
+ import type { LocalWorkspaceContext } from '@ai-workbench/connect/api';
7
7
  export interface EmployeeProviderOptions {
8
- currentUserTurn(request: RuntimeRequest): {
9
- turn: number;
10
- userMessageId: string;
11
- };
12
8
  getNetwork(): NetworkApi | undefined;
13
9
  workspace(request: RuntimeRequest): Promise<{
14
10
  id: string;
@@ -16,7 +12,6 @@ export interface EmployeeProviderOptions {
16
12
  }>;
17
13
  native(): Promise<{
18
14
  path: string;
19
- sha256: string;
20
15
  }>;
21
16
  argv?: SshArgv;
22
17
  io?: BrokerIo;
@@ -31,12 +26,9 @@ interface Admission {
31
26
  target: ConnectTarget;
32
27
  connection: ConnectionState;
33
28
  request: RuntimeRequest;
34
- stable: (signal?: AbortSignal) => Promise<unknown>;
35
29
  }
36
- /** Read-only local classification and explicit acceptance precede even ensureReady's SSH status. */
37
- export declare function acceptEmployeeUserTurn(get: () => ConnectApi | undefined, employee: EmployeeProviderOptions, agent: AgentDefinition, api: ConnectApi, request: RuntimeRequest): Promise<Readonly<LocalUserTurnAcceptance> | undefined>;
38
- /** Recheck the admitted read-only facts after readiness awaits, before the catalog command. */
39
- export declare function validateEmployeeUserTurn(get: () => ConnectApi | undefined, employee: EmployeeProviderOptions, api: ConnectApi, request: RuntimeRequest, connection: ConnectionState): Promise<void>;
30
+ /** Inspect the current local workspace once at turn start, before host readiness. */
31
+ export declare function inspectEmployeeWorkspace(get: () => ConnectApi | undefined, employee: EmployeeProviderOptions, agent: AgentDefinition, api: ConnectApi, request: RuntimeRequest): Promise<Readonly<LocalWorkspaceContext> | undefined>;
40
32
  /** Source admission is separate from L's legacy host project resolver. */
41
33
  export declare function createEmployeeProvider(get: () => ConnectApi | undefined, options: Options, agent: AgentDefinition): (input: Admission) => Promise<Runtime | undefined>;
42
34
  export {};