@ai-workbench/remote-agent 0.8.5 → 0.8.10

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 (180) hide show
  1. package/README.md +33 -8
  2. package/dist/acp.d.ts +22 -2
  3. package/dist/acp.js +143 -25
  4. package/dist/approval-label.d.ts +1 -1
  5. package/dist/approval-label.js +15 -3
  6. package/dist/broker-runtime.js +40 -8
  7. package/dist/broker.js +5 -1
  8. package/dist/claude-local.d.ts +37 -0
  9. package/dist/claude-local.js +207 -0
  10. package/dist/client.js +71 -2
  11. package/dist/conversation-details.d.ts +0 -1
  12. package/dist/conversation-details.js +37 -7
  13. package/dist/employee-endpoint.d.ts +91 -0
  14. package/dist/employee-endpoint.js +141 -0
  15. package/dist/employee-exec.d.ts +53 -0
  16. package/dist/employee-exec.js +423 -0
  17. package/dist/employee-location.d.ts +66 -0
  18. package/dist/employee-location.js +51 -0
  19. package/dist/employee-mcp.d.ts +42 -0
  20. package/dist/employee-mcp.js +181 -0
  21. package/dist/employee-native.d.ts +18 -0
  22. package/dist/employee-native.js +38 -0
  23. package/dist/employee-provider.d.ts +42 -0
  24. package/dist/employee-provider.js +326 -0
  25. package/dist/employee-relay.d.ts +18 -0
  26. package/dist/employee-relay.js +49 -0
  27. package/dist/employee-shell.d.ts +26 -0
  28. package/dist/employee-shell.js +89 -0
  29. package/dist/employee-ssh.d.ts +22 -0
  30. package/dist/employee-ssh.js +123 -0
  31. package/dist/employee-tools.d.ts +117 -0
  32. package/dist/employee-tools.js +292 -0
  33. package/dist/employee-workspace.d.ts +26 -0
  34. package/dist/employee-workspace.js +61 -0
  35. package/dist/index.d.ts +6 -0
  36. package/dist/index.js +148 -28
  37. package/dist/input.d.ts +11 -0
  38. package/dist/input.js +61 -23
  39. package/dist/local-user-turn.d.ts +24 -0
  40. package/dist/local-user-turn.js +103 -0
  41. package/dist/presentation.d.ts +1 -1
  42. package/dist/presentation.js +46 -2
  43. package/dist/provider.d.ts +36 -2
  44. package/dist/provider.js +33 -0
  45. package/dist/readiness.js +1 -1
  46. package/dist/recovery.d.ts +14 -1
  47. package/dist/recovery.js +11 -2
  48. package/dist/remote-details.d.ts +7 -0
  49. package/dist/remote-details.js +11 -1
  50. package/helpers/ripgrep/LICENSE-vscode +13 -0
  51. package/helpers/ripgrep/PROVENANCE.md +9 -0
  52. package/helpers/ripgrep/darwin-arm64/rg +0 -0
  53. package/helpers/ripgrep/darwin-x64/rg +0 -0
  54. package/helpers/ripgrep/manifest.json +56 -0
  55. package/helpers/ripgrep/notices/COPYING-ripgrep +3 -0
  56. package/helpers/ripgrep/notices/DEPENDENCIES.json +946 -0
  57. package/helpers/ripgrep/notices/LICENCE-PCRE2.md +103 -0
  58. package/helpers/ripgrep/notices/LICENSE-MIT-ripgrep +21 -0
  59. package/helpers/ripgrep/notices/UNLICENSE-ripgrep +24 -0
  60. package/helpers/ripgrep/notices/aho-corasick-1.1.3/COPYING +3 -0
  61. package/helpers/ripgrep/notices/aho-corasick-1.1.3/LICENSE-MIT +21 -0
  62. package/helpers/ripgrep/notices/aho-corasick-1.1.3/UNLICENSE +24 -0
  63. package/helpers/ripgrep/notices/anyhow-1.0.100/LICENSE-APACHE +176 -0
  64. package/helpers/ripgrep/notices/anyhow-1.0.100/LICENSE-MIT +23 -0
  65. package/helpers/ripgrep/notices/arbitrary-1.4.2/LICENSE-APACHE +201 -0
  66. package/helpers/ripgrep/notices/arbitrary-1.4.2/LICENSE-MIT +27 -0
  67. package/helpers/ripgrep/notices/bstr-1.12.0/COPYING +8 -0
  68. package/helpers/ripgrep/notices/bstr-1.12.0/LICENSE-APACHE +201 -0
  69. package/helpers/ripgrep/notices/bstr-1.12.0/LICENSE-MIT +21 -0
  70. package/helpers/ripgrep/notices/cc-1.2.41/LICENSE-APACHE +201 -0
  71. package/helpers/ripgrep/notices/cc-1.2.41/LICENSE-MIT +25 -0
  72. package/helpers/ripgrep/notices/cfg-if-1.0.4/LICENSE-APACHE +201 -0
  73. package/helpers/ripgrep/notices/cfg-if-1.0.4/LICENSE-MIT +25 -0
  74. package/helpers/ripgrep/notices/crossbeam-channel-0.5.15/LICENSE-APACHE +201 -0
  75. package/helpers/ripgrep/notices/crossbeam-channel-0.5.15/LICENSE-MIT +27 -0
  76. package/helpers/ripgrep/notices/crossbeam-channel-0.5.15/LICENSE-THIRD-PARTY +593 -0
  77. package/helpers/ripgrep/notices/crossbeam-deque-0.8.6/LICENSE-APACHE +201 -0
  78. package/helpers/ripgrep/notices/crossbeam-deque-0.8.6/LICENSE-MIT +27 -0
  79. package/helpers/ripgrep/notices/crossbeam-epoch-0.9.18/LICENSE-APACHE +201 -0
  80. package/helpers/ripgrep/notices/crossbeam-epoch-0.9.18/LICENSE-MIT +27 -0
  81. package/helpers/ripgrep/notices/crossbeam-utils-0.8.21/LICENSE-APACHE +201 -0
  82. package/helpers/ripgrep/notices/crossbeam-utils-0.8.21/LICENSE-MIT +27 -0
  83. package/helpers/ripgrep/notices/derive_arbitrary-1.4.2/LICENSE-APACHE +201 -0
  84. package/helpers/ripgrep/notices/derive_arbitrary-1.4.2/LICENSE-MIT +27 -0
  85. package/helpers/ripgrep/notices/encoding_rs-0.8.35/COPYRIGHT +17 -0
  86. package/helpers/ripgrep/notices/encoding_rs-0.8.35/LICENSE-APACHE +202 -0
  87. package/helpers/ripgrep/notices/encoding_rs-0.8.35/LICENSE-MIT +25 -0
  88. package/helpers/ripgrep/notices/encoding_rs-0.8.35/LICENSE-WHATWG +26 -0
  89. package/helpers/ripgrep/notices/encoding_rs_io-0.1.7/COPYING +8 -0
  90. package/helpers/ripgrep/notices/encoding_rs_io-0.1.7/LICENSE-APACHE +201 -0
  91. package/helpers/ripgrep/notices/encoding_rs_io-0.1.7/LICENSE-MIT +21 -0
  92. package/helpers/ripgrep/notices/find-msvc-tools-0.1.4/LICENSE-APACHE +201 -0
  93. package/helpers/ripgrep/notices/find-msvc-tools-0.1.4/LICENSE-MIT +25 -0
  94. package/helpers/ripgrep/notices/getrandom-0.3.4/LICENSE-APACHE +201 -0
  95. package/helpers/ripgrep/notices/getrandom-0.3.4/LICENSE-MIT +26 -0
  96. package/helpers/ripgrep/notices/glob-0.3.3/LICENSE-APACHE +201 -0
  97. package/helpers/ripgrep/notices/glob-0.3.3/LICENSE-MIT +25 -0
  98. package/helpers/ripgrep/notices/itoa-1.0.15/LICENSE-APACHE +176 -0
  99. package/helpers/ripgrep/notices/itoa-1.0.15/LICENSE-MIT +23 -0
  100. package/helpers/ripgrep/notices/jobserver-0.1.34/LICENSE-APACHE +201 -0
  101. package/helpers/ripgrep/notices/jobserver-0.1.34/LICENSE-MIT +25 -0
  102. package/helpers/ripgrep/notices/lexopt-0.3.1/LICENSE +19 -0
  103. package/helpers/ripgrep/notices/libc-0.2.177/LICENSE-APACHE +176 -0
  104. package/helpers/ripgrep/notices/libc-0.2.177/LICENSE-MIT +25 -0
  105. package/helpers/ripgrep/notices/log-0.4.28/LICENSE-APACHE +201 -0
  106. package/helpers/ripgrep/notices/log-0.4.28/LICENSE-MIT +25 -0
  107. package/helpers/ripgrep/notices/memchr-2.7.6/COPYING +3 -0
  108. package/helpers/ripgrep/notices/memchr-2.7.6/LICENSE-MIT +21 -0
  109. package/helpers/ripgrep/notices/memchr-2.7.6/UNLICENSE +24 -0
  110. package/helpers/ripgrep/notices/memmap2-0.9.8/LICENSE-APACHE +201 -0
  111. package/helpers/ripgrep/notices/memmap2-0.9.8/LICENSE-MIT +26 -0
  112. package/helpers/ripgrep/notices/msvc_spectre_libs-0.1.3/LICENSE +21 -0
  113. package/helpers/ripgrep/notices/pcre2-0.2.11/COPYING +3 -0
  114. package/helpers/ripgrep/notices/pcre2-0.2.11/LICENSE-MIT +21 -0
  115. package/helpers/ripgrep/notices/pcre2-0.2.11/UNLICENSE +24 -0
  116. package/helpers/ripgrep/notices/pcre2-sys-0.2.10/COPYING +3 -0
  117. package/helpers/ripgrep/notices/pcre2-sys-0.2.10/LICENSE-MIT +21 -0
  118. package/helpers/ripgrep/notices/pcre2-sys-0.2.10/UNLICENSE +24 -0
  119. package/helpers/ripgrep/notices/pkg-config-0.3.32/LICENSE-APACHE +201 -0
  120. package/helpers/ripgrep/notices/pkg-config-0.3.32/LICENSE-MIT +25 -0
  121. package/helpers/ripgrep/notices/proc-macro2-1.0.101/LICENSE-APACHE +176 -0
  122. package/helpers/ripgrep/notices/proc-macro2-1.0.101/LICENSE-MIT +23 -0
  123. package/helpers/ripgrep/notices/quote-1.0.41/LICENSE-APACHE +176 -0
  124. package/helpers/ripgrep/notices/quote-1.0.41/LICENSE-MIT +23 -0
  125. package/helpers/ripgrep/notices/r-efi-5.3.0/AUTHORS +74 -0
  126. package/helpers/ripgrep/notices/regex-1.12.2/LICENSE-APACHE +201 -0
  127. package/helpers/ripgrep/notices/regex-1.12.2/LICENSE-MIT +25 -0
  128. package/helpers/ripgrep/notices/regex-automata-0.4.13/LICENSE-APACHE +201 -0
  129. package/helpers/ripgrep/notices/regex-automata-0.4.13/LICENSE-MIT +25 -0
  130. package/helpers/ripgrep/notices/regex-syntax-0.8.8/LICENSE-APACHE +201 -0
  131. package/helpers/ripgrep/notices/regex-syntax-0.8.8/LICENSE-MIT +25 -0
  132. package/helpers/ripgrep/notices/regex-syntax-0.8.8/src/unicode_tables/LICENSE-UNICODE +57 -0
  133. package/helpers/ripgrep/notices/ryu-1.0.20/LICENSE-APACHE +176 -0
  134. package/helpers/ripgrep/notices/ryu-1.0.20/LICENSE-BOOST +23 -0
  135. package/helpers/ripgrep/notices/same-file-1.0.6/COPYING +3 -0
  136. package/helpers/ripgrep/notices/same-file-1.0.6/LICENSE-MIT +21 -0
  137. package/helpers/ripgrep/notices/same-file-1.0.6/UNLICENSE +24 -0
  138. package/helpers/ripgrep/notices/serde-1.0.228/LICENSE-APACHE +176 -0
  139. package/helpers/ripgrep/notices/serde-1.0.228/LICENSE-MIT +23 -0
  140. package/helpers/ripgrep/notices/serde_core-1.0.228/LICENSE-APACHE +176 -0
  141. package/helpers/ripgrep/notices/serde_core-1.0.228/LICENSE-MIT +23 -0
  142. package/helpers/ripgrep/notices/serde_derive-1.0.228/LICENSE-APACHE +176 -0
  143. package/helpers/ripgrep/notices/serde_derive-1.0.228/LICENSE-MIT +23 -0
  144. package/helpers/ripgrep/notices/serde_json-1.0.145/LICENSE-APACHE +176 -0
  145. package/helpers/ripgrep/notices/serde_json-1.0.145/LICENSE-MIT +23 -0
  146. package/helpers/ripgrep/notices/shlex-1.3.0/LICENSE-APACHE +13 -0
  147. package/helpers/ripgrep/notices/shlex-1.3.0/LICENSE-MIT +21 -0
  148. package/helpers/ripgrep/notices/syn-2.0.106/LICENSE-APACHE +176 -0
  149. package/helpers/ripgrep/notices/syn-2.0.106/LICENSE-MIT +23 -0
  150. package/helpers/ripgrep/notices/termcolor-1.4.1/COPYING +3 -0
  151. package/helpers/ripgrep/notices/termcolor-1.4.1/LICENSE-MIT +21 -0
  152. package/helpers/ripgrep/notices/termcolor-1.4.1/UNLICENSE +24 -0
  153. package/helpers/ripgrep/notices/textwrap-0.16.2/LICENSE +21 -0
  154. package/helpers/ripgrep/notices/tikv-jemalloc-sys-0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7/LICENSE-APACHE +201 -0
  155. package/helpers/ripgrep/notices/tikv-jemalloc-sys-0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7/LICENSE-MIT +25 -0
  156. package/helpers/ripgrep/notices/tikv-jemalloc-sys-0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7/jemalloc/COPYING +27 -0
  157. package/helpers/ripgrep/notices/tikv-jemallocator-0.6.0/LICENSE-APACHE +201 -0
  158. package/helpers/ripgrep/notices/tikv-jemallocator-0.6.0/LICENSE-MIT +25 -0
  159. package/helpers/ripgrep/notices/unicode-ident-1.0.19/LICENSE-APACHE +176 -0
  160. package/helpers/ripgrep/notices/unicode-ident-1.0.19/LICENSE-MIT +23 -0
  161. package/helpers/ripgrep/notices/unicode-ident-1.0.19/LICENSE-UNICODE +39 -0
  162. package/helpers/ripgrep/notices/walkdir-2.5.0/COPYING +3 -0
  163. package/helpers/ripgrep/notices/walkdir-2.5.0/LICENSE-MIT +21 -0
  164. package/helpers/ripgrep/notices/walkdir-2.5.0/UNLICENSE +24 -0
  165. package/helpers/ripgrep/notices/wasip2-1.0.1+wasi-0.2.4/LICENSE-APACHE +201 -0
  166. package/helpers/ripgrep/notices/wasip2-1.0.1+wasi-0.2.4/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
  167. package/helpers/ripgrep/notices/wasip2-1.0.1+wasi-0.2.4/LICENSE-MIT +23 -0
  168. package/helpers/ripgrep/notices/winapi-util-0.1.11/COPYING +3 -0
  169. package/helpers/ripgrep/notices/winapi-util-0.1.11/LICENSE-MIT +21 -0
  170. package/helpers/ripgrep/notices/winapi-util-0.1.11/UNLICENSE +24 -0
  171. package/helpers/ripgrep/notices/windows-link-0.2.1/license-apache-2.0 +201 -0
  172. package/helpers/ripgrep/notices/windows-link-0.2.1/license-mit +21 -0
  173. package/helpers/ripgrep/notices/windows-sys-0.61.2/license-apache-2.0 +201 -0
  174. package/helpers/ripgrep/notices/windows-sys-0.61.2/license-mit +21 -0
  175. package/helpers/ripgrep/notices/wit-bindgen-0.46.0/LICENSE-APACHE +201 -0
  176. package/helpers/ripgrep/notices/wit-bindgen-0.46.0/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
  177. package/helpers/ripgrep/notices/wit-bindgen-0.46.0/LICENSE-MIT +23 -0
  178. package/locale/en.json +1 -1
  179. package/locale/zh.json +2 -2
  180. package/package.json +29 -11
@@ -0,0 +1,103 @@
1
+ import { SessionId } from '@deepseek-ai/dsh-session';
2
+ import { isDeepStrictEqual } from 'node:util';
3
+ import { NeedError } from "./remote.js";
4
+ const failure = (code = 'REMOTE_DETAIL_SCOPE_INVALID') => new NeedError(code, '本轮输入无法核对,已停止本次处理。', '官方当前员工输入与所选远程品牌');
5
+ /** CAS expectation only. L independently establishes live human-turn/brand evidence. */
6
+ export async function readLocalUserTurn(ctx, request) {
7
+ request = structuredClone(request);
8
+ const id = SessionId(request.sessionId), sessions = ctx.get('sessions'), session = sessions?.get(id);
9
+ const persistence = ctx.get('sessionPersistence');
10
+ if (!session || typeof sessions?.flush !== 'function' || !persistence?.identity || typeof persistence.open !== 'function' || !request.userMessageIds.length)
11
+ throw failure();
12
+ const watermark = session.seq, header = structuredClone(session.header), persistenceIdentity = persistence.identity;
13
+ const assertCurrent = () => { if (ctx.get('sessions')?.get(id) !== session || ctx.get('sessionPersistence')?.identity !== persistenceIdentity || session.seq !== watermark || !isDeepStrictEqual(session.header, header))
14
+ throw failure('LOCAL_USER_TURN_CHANGED'); };
15
+ assertCurrent();
16
+ if (!await sessions.flush(session))
17
+ throw failure();
18
+ assertCurrent();
19
+ const handle = await persistence.open(id, 'read');
20
+ let proof, firstFailure;
21
+ try {
22
+ assertCurrent();
23
+ if (handle.id !== id || handle.access !== 'read' || !isDeepStrictEqual(handle.header, header) || handle.inheritedEventCount !== session.inheritedEventCount)
24
+ throw failure();
25
+ const { events } = await handle.read();
26
+ assertCurrent();
27
+ if (!Array.isArray(events) || events.length !== watermark)
28
+ throw failure();
29
+ let turn, step, input, route, routeContext;
30
+ for (let i = 0; i < events.length; i++) {
31
+ const e = events[i];
32
+ if (e.seq !== i)
33
+ throw failure();
34
+ if (e.type === 'turn/start') {
35
+ turn = e;
36
+ step = undefined;
37
+ input = undefined;
38
+ }
39
+ else if (e.type === 'turn/end') {
40
+ turn = undefined;
41
+ step = undefined;
42
+ input = undefined;
43
+ }
44
+ else if (e.type === 'step/start') {
45
+ step = e;
46
+ input = undefined;
47
+ }
48
+ else if (e.type === 'step/end') {
49
+ step = undefined;
50
+ input = undefined;
51
+ }
52
+ else if (e.type === 'user/message' && step && e.data.source.kind === 'user')
53
+ input = e;
54
+ else if (e.type === 'request/header')
55
+ route = e.data.header.config.provider;
56
+ else if (e.type === 'request/context')
57
+ routeContext = e.data.provider;
58
+ }
59
+ if (!turn || !step || step.data.turn !== turn.data.turn || !input || route !== request.route || routeContext !== undefined && routeContext !== request.route || !session.isOwnSeq(turn.seq) || !session.isOwnSeq(step.seq) || !session.isOwnSeq(input.seq) || !request.userMessageIds.includes(input.data.id))
60
+ throw failure();
61
+ proof = { expectedUserTurn: { turn: turn.data.turn, userMessageId: input.data.id }, startSequence: turn.seq, userMessageSequence: input.seq };
62
+ }
63
+ catch (error) {
64
+ firstFailure = error;
65
+ }
66
+ try {
67
+ await handle.close();
68
+ }
69
+ catch (error) {
70
+ if (firstFailure instanceof NeedError)
71
+ throw Object.assign(new NeedError(firstFailure.code, firstFailure.message, firstFailure.requires + ';持久句柄关闭失败'), { cause: new AggregateError([firstFailure, error], 'LOCAL_TURN_READ_AND_CLOSE_FAILED') });
72
+ if (firstFailure !== undefined)
73
+ throw new AggregateError([firstFailure, error], 'LOCAL_TURN_READ_AND_CLOSE_FAILED');
74
+ throw error;
75
+ }
76
+ if (firstFailure !== undefined)
77
+ throw firstFailure;
78
+ assertCurrent();
79
+ return { ...proof, assertCurrent };
80
+ }
81
+ /** Only metadata observed live since this plugin mounted; never seed or persisted tails. */
82
+ export function createLocalUserTurnObserver(ctx) {
83
+ const current = new WeakMap();
84
+ ctx.on('session/event', (session, event) => {
85
+ if (event.type === 'turn/start')
86
+ current.set(session, { turn: event.data.turn });
87
+ else if (event.type === 'turn/end')
88
+ current.delete(session);
89
+ else if (event.type === 'user/message' && event.data.source.kind === 'user') {
90
+ const turn = current.get(session);
91
+ if (turn)
92
+ turn.userMessageId = event.data.id;
93
+ }
94
+ });
95
+ ctx.on('session/disposed', session => current.delete(session));
96
+ return { current(request) {
97
+ const session = request.sessionId ? ctx.get('sessions')?.get(SessionId(request.sessionId)) : undefined;
98
+ const metadata = session ? current.get(session) : undefined;
99
+ if (!metadata || !Number.isSafeInteger(metadata.turn) || metadata.turn < 0 || !metadata.userMessageId || !request.userInputIds?.includes(metadata.userMessageId))
100
+ throw new NeedError('LOCAL_USER_TURN_UNCONFIRMED', '无法核对本次员工输入,本轮已停止。', '本插件启用后观察到的官方真实员工输入');
101
+ return { turn: metadata.turn, userMessageId: metadata.userMessageId };
102
+ } };
103
+ }
@@ -3,4 +3,4 @@ export declare const REMOTE_CODEX_NAME = "Codex\uFF08\u8FDC\u7A0B\u4E3B\u673A\uF
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
  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
5
  /** Employee failures use business language; diagnostic codes remain separately available. */
6
- export declare function employeeFailure(code: string): string;
6
+ export declare function employeeFailure(code: string, brand?: 'codex' | 'claude'): string;
@@ -3,11 +3,19 @@ export const REMOTE_CODEX_NAME = 'Codex(远程主机)';
3
3
  export const CONNECTION_REQUIRED = '远程主机连接组件没有装好,请联系管理员。';
4
4
  export const TEST_HOST_NOTICE = '远程主机正在使用测试配置,遇到问题请联系管理员。';
5
5
  /** Employee failures use business language; diagnostic codes remain separately available. */
6
- export function employeeFailure(code) {
6
+ export function employeeFailure(code, brand = 'codex') {
7
7
  const messages = {
8
+ LOCAL_USER_TURN_CHANGED: '本次输入已变化,本轮已停止,请确认对话后重新发送。',
9
+ LOCAL_USER_TURN_UNCONFIRMED: '无法核对本次员工输入,本轮已停止;请在当前会话重新发送。',
10
+ LOCAL_USER_TURN_ACCEPTANCE_INVALID: '本次输入的核验回执不一致,本轮已停止,请联系管理员。',
8
11
  TECHNICAL_DETAILS_UNAVAILABLE: '技术详情暂不可用,请更新远程主机连接组件。',
9
12
  REMOTE_DETAIL_STORAGE_FAILED: '技术详情保存失败,本轮已停止,请联系管理员检查。',
10
13
  REMOTE_DETAIL_DELIVERY_UNKNOWN: '技术详情的持久结果无法核对,本轮已停止。',
14
+ REMOTE_DETAIL_SCOPE_INVALID: '无法核对当前会话的技术详情,本轮已停止;我需要更新后的远程主机连接组件。',
15
+ EMPLOYEE_CONTEXT_UNAVAILABLE: '我需要远程主机连接组件提供当前本机工作区,本轮未执行。',
16
+ EMPLOYEE_ENDPOINT_UNAVAILABLE: '我需要员工电脑的执行连接就绪,本轮未执行;请联系管理员检查连接组件。',
17
+ EMPLOYEE_CONTEXT_CHANGED: '本机文件夹或连接已改变,原工具已停止;请在当前工作区重新开始。',
18
+ EMPLOYEE_WORKSPACE_INVALID: '无法核对这条对话所属的本机文件夹,本轮未执行;请在工作区中重新打开对话。',
11
19
  REMOTE_DETAIL_TOO_LARGE: '技术详情超过已配置的单事件容量,本轮已停止;请联系管理员调整conversationDetails.maxEventBytes。',
12
20
  DEPENDENCY_REQUIRED: CONNECTION_REQUIRED,
13
21
  LOGIN_REQUIRED: '需要登录,请到设置 → 远程主机连接 点登录',
@@ -33,6 +41,12 @@ export function employeeFailure(code) {
33
41
  CONTENT_UNSUPPORTED: '远程 Codex 暂不支持这类附件,请联系管理员。',
34
42
  SYSTEM_PROMPT_UPDATE_PENDING: 'Claude原会话无法保证立即应用已变化的系统或开发者要求,本轮未发送;请新建会话应用新要求。',
35
43
  SYSTEM_PROMPT_UNSUPPORTED: '远端没有声明系统与开发者上下文能力,本轮未发送;需要管理员提供支持该能力的远端适配器。',
44
+ SYSTEM_CONTEXT_TYPE_UNSUPPORTED: '系统或开发者要求包含暂不支持的非文本内容,本轮未新建或发送;请使用文本要求或联系管理员。',
45
+ RECOVERY_CONTEXT_POLICY_UNSUPPORTED: '旧版会话恢复记录仍绑定模型要求,无法安全接回;本轮未发送,请联系管理员核对原会话。',
46
+ SYSTEM_PROMPT_POLICY_UNSUPPORTED: '远端还不支持保留原会话并按新要求继续,请联系管理员更新远端适配器;本轮未发送。',
47
+ SYSTEM_PROMPT_NEW_SESSION_REQUIRED: '会话要求已变化,需要新建 Codex 会话并承接历史后继续;本轮未发送。',
48
+ SESSION_CONTEXT_DIGEST_INVALID: '原会话的要求记录无法核对,本轮未发送;请联系管理员核对原会话。',
49
+ HISTORY_CONTENT_UNSUPPORTED: '此前对话含有暂时无法完整承接的内容,本轮未新建或发送;请联系管理员检查历史内容类型。',
36
50
  SYSTEM_PROMPT_UPDATE_UNSUPPORTED: '远端不能更新原会话的系统与开发者要求,本轮未发送;请新建会话。',
37
51
  PROMPT_CONTENT_UNSUPPORTED: '远端没有声明这类输入能力,本轮未发送;请使用受支持的内容或联系管理员。',
38
52
  ATTACHMENT_REQUIRED: '我需要官方附件组件读取这张图片,请联系管理员检查组件。',
@@ -45,5 +59,35 @@ export function employeeFailure(code) {
45
59
  MODEL_RESOLUTION_UNCONFIRMED: '所选模型的具体型号尚未获得当前会话确认,本轮未发送;请重新选择模型或联系管理员。',
46
60
  REMOTE_CLEANUP_UNCONFIRMED: '原主机会话的清理结果尚未确认,已阻断继续发送;请联系管理员核对,不能自动重开。',
47
61
  };
48
- return messages[code] ?? `远程主机暂时无法完成这次操作,请联系管理员。技术详情:诊断代码 ${code}`;
62
+ if (messages[code])
63
+ return messages[code];
64
+ if (code === 'EMPLOYEE_OPERATION_UNSUPPORTED')
65
+ return '当前本机工作区暂不支持单次运行和断开后的冷恢复;请使用会话模式新建会话,原记录保留可查。';
66
+ if (code === 'AW_EMPLOYEE_COLD_RESUME_UNSUPPORTED' || code === 'EMPLOYEE_RECOVERY_UNSUPPORTED')
67
+ return '当前版本暂不支持恢复已关闭的本机执行会话;请新建会话,原记录保留可查。';
68
+ if (code === 'AW_EMPLOYEE_HOST_AUXILIARY_CONFIG_UNSUPPORTED')
69
+ return '当前主机启用的MCP、hooks或插件尚未支持改到员工电脑,本轮没有执行,请联系管理员。';
70
+ if (code === 'AW_EMPLOYEE_HOST_PROJECT_CONFIG_UNSUPPORTED')
71
+ return '主机上存在与本机工作区路径重合的项目配置,当前版本无法安全应用,本轮没有执行,请联系管理员。';
72
+ if (code === 'AW_EMPLOYEE_EXECUTOR_MCP_UNSUPPORTED')
73
+ return '本机工作区配置了附加MCP工具,当前版本尚不支持这类工具,本轮没有继续执行。';
74
+ if (['AW_EMPLOYEE_CONFIG_ADMISSION_INVALID', 'AW_EMPLOYEE_CONFIG_ADMISSION_FAILED', 'AW_EMPLOYEE_EXECUTOR_CONFIG_PROTOCOL_INVALID', 'AW_EMPLOYEE_EXECUTOR_CONFIG_READ_FAILED'].includes(code))
75
+ return '无法核验这次本机工作区的助手配置,本轮没有继续执行,请联系管理员查看技术详情。';
76
+ if (code === 'AW_EMPLOYEE_MCP_UNSUPPORTED')
77
+ return '当前版本尚不支持把附加MCP工具改到员工电脑,本轮没有执行。';
78
+ if (code === 'AW_EMPLOYEE_HOST_AUXILIARY_UNSUPPORTED')
79
+ return '这项辅助操作尚未支持在员工电脑执行,本轮没有执行。';
80
+ if (code === 'AW_EMPLOYEE_SLASH_COMMAND_UNSUPPORTED')
81
+ return '这项快捷命令暂不支持本机执行,请直接描述任务。';
82
+ if (code === 'AW_EMPLOYEE_HOST_FILE_REPORT_UNSUPPORTED')
83
+ return '这项文件报告暂不支持本机工作区;请查看对话和技术详情中的已有执行记录。';
84
+ if (code === 'AW_EMPLOYEE_CONFIG_DISCOVERY_OVERRIDE_UNSUPPORTED')
85
+ return '当前助手的项目配置覆盖与本机执行不兼容,本轮没有执行,请联系管理员。';
86
+ if (code === 'EMPLOYEE_PLATFORM_UNSUPPORTED')
87
+ return brand === 'claude' ? '本机执行目前只支持Mac;当前设备尚不支持,本轮未执行。' : '当前版本的Codex本机执行仅验证了Apple芯片Mac,本轮没有执行。';
88
+ if (code.startsWith('AW_EMPLOYEE_BINARY_'))
89
+ return 'Codex本机执行组件缺失或校验失败,本轮没有执行,请联系管理员。';
90
+ if (code.startsWith('AW_EMPLOYEE_') || code.startsWith('EMPLOYEE_'))
91
+ return '员工电脑的执行连接不可用或工作区已变化,本轮已停止;在途操作结果尚待确认,请查看技术详情。';
92
+ return `远程主机暂时无法完成这次操作,请联系管理员。技术详情:诊断代码 ${code}`;
49
93
  }
@@ -11,9 +11,23 @@ import type { DetailChannel } from './remote-details.ts';
11
11
  import type { WorkspaceNoticePresentation } from './workspace-notice.ts';
12
12
  import { StageTiming } from './stage-timing.ts';
13
13
  import type { RecoveryJournal, AcpRecovery } from './recovery.ts';
14
+ import type { EmployeeProviderOptions } from './employee-provider.ts';
15
+ import type { LocalUserTurnAcceptance } from '@ai-workbench/connect/api';
16
+ import type { EmployeeRouting } from './employee-relay.ts';
17
+ export interface EmployeeExecution {
18
+ hostCwd: string;
19
+ routing: EmployeeRouting;
20
+ notice: string;
21
+ scope: Record<string, unknown>;
22
+ signal?: AbortSignal;
23
+ beginTurn(signal: AbortSignal): Promise<void>;
24
+ endTurn(): void;
25
+ validate(signal?: AbortSignal): Promise<void>;
26
+ }
14
27
  export interface Runtime {
15
28
  identity: string;
16
29
  cwd: string;
30
+ execution?: EmployeeExecution;
17
31
  acpTransport?: {
18
32
  writable: WritableStream<Uint8Array>;
19
33
  readable: ReadableStream<Uint8Array>;
@@ -39,13 +53,28 @@ export interface Runtime {
39
53
  turn: string | number | null;
40
54
  step: string | number | null;
41
55
  };
56
+ employeeExecutionMeta?: {
57
+ version: 1;
58
+ bindingId: string;
59
+ workspaceId: string;
60
+ cwd: string;
61
+ acpMaxMessageBytes: number;
62
+ };
63
+ employeeExecution?: (params: unknown, signal?: AbortSignal) => Promise<Record<string, unknown>>;
64
+ employeePresentation?: string;
42
65
  }
43
66
  export interface RuntimeRequest extends Invocation {
67
+ userInputIds?: readonly string[];
68
+ localAcceptance?: Readonly<LocalUserTurnAcceptance>;
69
+ localAdmissionCheck?: () => void;
70
+ readonly localAcceptanceId?: string;
71
+ userMessageIds?: readonly string[];
44
72
  recoveryJournal?: RecoveryJournal;
45
73
  detailChannel?: DetailChannel;
46
74
  validateContext?: (ignoreCancellation?: boolean) => Promise<void>;
47
75
  verifyRecovery?: () => Promise<boolean>;
48
76
  acpMaxMessageBytes?: number;
77
+ employeeScope?: string;
49
78
  contextSha256?: string;
50
79
  resumeSessionId?: string;
51
80
  recoveryCheckpointId?: string;
@@ -106,7 +135,7 @@ type Result<T> = {
106
135
  } & Pick<ConnectNeed, 'officialReason'>;
107
136
  };
108
137
  /** 消费正式connect-api 0.7公开子集;X不响应L登录票据、不直接调用登录。 */
109
- export interface ConnectApi extends Pick<LConnectApi, 'getConnectionState' | 'getLoginPromptState' | 'requestLoginPrompt' | 'refreshLoginPrompts'>, Partial<NativeWorkspaceApi>, Partial<Pick<LConnectApi, 'getWorkspaceBindingState' | 'getModelCatalogTarget' | 'onConnectionState' | 'onLoginPromptState' | 'appendRemoteConversationDetail' | 'getRemoteConversationDetailReceipt' | 'listRemoteConversationDetails'>> {
138
+ export interface ConnectApi extends Pick<LConnectApi, 'getConnectionState' | 'getLoginPromptState' | 'requestLoginPrompt' | 'refreshLoginPrompts'>, Partial<NativeWorkspaceApi>, Partial<Pick<LConnectApi, 'getWorkspaceBindingState' | 'getModelCatalogTarget' | 'onConnectionState' | 'onLoginPromptState' | 'appendRemoteConversationDetail' | 'getRemoteConversationDetailReceipt' | 'listRemoteConversationDetails' | 'getWorkspaceLocationState' | 'getLocalWorkspaceContext' | 'onWorkspaceLocationState' | 'acceptLocalWorkspaceUserTurn'>> {
110
139
  getState?(): ConnectState;
111
140
  getSshTarget(): Promise<Result<ConnectTarget>>;
112
141
  checkLogin(provider: LoginProvider): Promise<Result<{
@@ -130,7 +159,7 @@ export declare function requireLoginCoordinator(api: ConnectApi): void;
130
159
  export declare function requireLoginState(state: LoginPromptState): void;
131
160
  declare module '@deepseek-ai/cordis' {
132
161
  interface Context {
133
- aiWorkbenchConnect: ConnectApi;
162
+ aiWorkbenchConnect: LConnectApi;
134
163
  }
135
164
  interface Events {
136
165
  'ai-workbench/connection-state': (state: ConnectionState) => void;
@@ -152,11 +181,16 @@ export interface NoticeConsumer {
152
181
  reconcile(request: RuntimeRequest, api: ConnectApi): Promise<void>;
153
182
  deliver(notice: WorkspaceNotice, resolved: SessionProjectTarget, request: RuntimeRequest, api: ConnectApi): Promise<WorkspaceNoticePresentation | void>;
154
183
  }
184
+ export type LocalRuntimeProvider = ((request: RuntimeRequest, api: ConnectApi, connection: ConnectionState, target: ConnectTarget) => Promise<Runtime | undefined>) & {
185
+ admit?: (request: RuntimeRequest, api: ConnectApi, connection: ConnectionState, target: ConnectTarget) => Promise<void>;
186
+ };
155
187
  export declare function sameTarget(a: ConnectTarget, b: ConnectTarget): boolean;
156
188
  export declare function connectProvider(get: () => ConnectApi | undefined, options?: {
157
189
  agent?: AgentDefinition;
158
190
  ask?: Interaction;
159
191
  notice?: NoticeConsumer;
192
+ employee?: EmployeeProviderOptions;
193
+ local?: LocalRuntimeProvider;
160
194
  details?: (request: RuntimeRequest, api: ConnectApi, connection: ConnectionState, target: ConnectTarget) => Promise<DetailChannel>;
161
195
  open?: (target: ConnectTarget, project: Project, request: RuntimeRequest) => Promise<Runtime>;
162
196
  }): RuntimeProvider;
package/dist/provider.js CHANGED
@@ -154,6 +154,9 @@ export function sameTarget(a, b) {
154
154
  }
155
155
  export function connectProvider(get, options = {}) {
156
156
  const agent = options.agent ?? CODEX_AGENT;
157
+ // Keep the legacy source SDK wrapper's strip-only import graph free of broker runtime syntax.
158
+ // Cache the initialization promise so concurrent sessions share this provider's binding lifetimes.
159
+ let employee;
157
160
  const admissions = new WeakMap();
158
161
  const preflight = async (request) => {
159
162
  request.timing ??= new StageTiming();
@@ -165,7 +168,12 @@ export function connectProvider(get, options = {}) {
165
168
  requireLoginCoordinator(api);
166
169
  if (request.mode === 'one-shot' && !agent.oneShot)
167
170
  throw new NeedError('MODE_UNSUPPORTED', '此远程模型仅支持会话模式', '使用会话模式');
171
+ if (options.employee) {
172
+ const module = await import("./employee-provider.js");
173
+ request.localAcceptance = await module.acceptEmployeeUserTurn(get, options.employee, agent, api, request);
174
+ }
168
175
  const { target, connection } = await request.timing.run('login-ready', async () => {
176
+ request.localAdmissionCheck?.();
169
177
  const before = api.getConnectionState();
170
178
  const target = await ensureReady(api, agent.loginProvider, request.signal);
171
179
  validateTarget(target);
@@ -177,7 +185,11 @@ export function connectProvider(get, options = {}) {
177
185
  });
178
186
  if (request.identity && request.identity !== identity(target))
179
187
  throw new NeedError('SESSION_CONTEXT_MISMATCH', '员工主机与原会话不一致,请新建会话', '原员工主机');
188
+ if (options.employee && request.localAcceptance)
189
+ await (await import("./employee-provider.js")).validateEmployeeUserTurn(get, options.employee, api, request, connection);
190
+ request.localAdmissionCheck?.();
180
191
  admissions.set(request, { api, target, connection });
192
+ await options.local?.admit?.(request, api, connection, target);
181
193
  };
182
194
  const resolve = async (request) => {
183
195
  if (!admissions.has(request))
@@ -189,6 +201,27 @@ export function connectProvider(get, options = {}) {
189
201
  await stable();
190
202
  if (!request.sessionId)
191
203
  throw new NeedError('PROJECT_BINDING_REQUIRED', '我需要当前会话和已选择的工作区,请使用原生工作区入口', 'DSH会话与原生工作区');
204
+ if (options.employee) {
205
+ employee ??= import("./employee-provider.js").then(module => module.createEmployeeProvider(get, options, agent));
206
+ const local = await (await employee)({ api, target, connection, request, stable: signal => request.timing.run('connection-confirm', () => waitForLogin(api, agent.loginProvider, connection, get, signal)) });
207
+ if (local) {
208
+ local.loginRequired = () => offerLogin(api, request, get, agent);
209
+ return local;
210
+ }
211
+ }
212
+ if (agent.loginProvider === 'claude' && options.local) {
213
+ const runtime = await options.local(request, api, connection, target);
214
+ if (runtime) {
215
+ try {
216
+ await stable();
217
+ }
218
+ catch (error) {
219
+ await runtime.dispose?.();
220
+ throw error;
221
+ }
222
+ return runtime;
223
+ }
224
+ }
192
225
  await options.notice?.reconcile(request, api);
193
226
  await stable();
194
227
  const resolved = await request.timing.run('workspace-resolve', async () => unwrap(await awaitL(() => api.resolveSessionProject(request.sessionId, { provider: agent.loginProvider, purpose: 'user-turn' }), request.signal)));
package/dist/readiness.js CHANGED
@@ -46,7 +46,7 @@ function details(target) {
46
46
  return [{ label: '主机配置', value: h.enforcement }, { label: '检查退出码', value: String(h.checkExitCode) }, ...h.failedChecks.map(item => ({ label: '未通过检查', value: `${item.id}(${item.status})` })), ...h.unverifiedChecks.map(item => ({ label: '未核实检查', value: `${item.id}(${item.status})` }))];
47
47
  }
48
48
  function blocked(code, technical = [], agent = CODEX_AGENT) {
49
- return { phase: 'blocked', loginStatus: 'unknown', title: `无法确认 ${agent.name.zh} 登录状态`, message: employeeFailure(code), technical: [...technical, { label: '诊断代码', value: code }] };
49
+ return { phase: 'blocked', loginStatus: 'unknown', title: `无法确认 ${agent.name.zh} 登录状态`, message: employeeFailure(code, agent.loginProvider), technical: [...technical, { label: '诊断代码', value: code }] };
50
50
  }
51
51
  /** L owns both evidence and inquiry. Missing per-brand evidence is never false. */
52
52
  function snapshot(api, agent = CODEX_AGENT) {
@@ -27,8 +27,21 @@ export interface RecoveryJournal {
27
27
  write(state: RecoveryState): Promise<void>;
28
28
  }
29
29
  export declare function validateRecovery(value: unknown): RecoveryState;
30
- /** Only negotiated booleans/known empty capability markers, never agent metadata. */
30
+ export declare const codexContextPolicy: Readonly<{
31
+ version: 1;
32
+ scope: "new-session";
33
+ mode: "append";
34
+ content: "text";
35
+ resume: "omit-only";
36
+ changed: "new-session-required";
37
+ mapping: "developerInstructions";
38
+ nativeCliUnmodified: true;
39
+ }>;
40
+ export declare function supportsCodexContextPolicy(capabilities: AgentCapabilities): boolean;
41
+ /** Known capabilities plus the exact Codex policy whitelist; no arbitrary metadata. */
31
42
  export declare function recoveryCapabilities(c: AgentCapabilities): AgentCapabilities;
32
43
  export declare function recoveryKey(value: unknown): string;
44
+ /** Preserve legacy lookup bytes; each employee endpoint scope owns a separate journal. */
45
+ export declare function runtimeRecoveryKey(identity: string, provider: string, sessionId: string | undefined, employeeScope?: string): string;
33
46
  /** History is immutable; current is atomically replaced only after fsync. No expiry. */
34
47
  export declare function recoveryJournal(profileDir: string, key: string): RecoveryJournal;
package/dist/recovery.js CHANGED
@@ -15,11 +15,20 @@ export function validateRecovery(value) {
15
15
  throw invalid();
16
16
  return structuredClone(s);
17
17
  }
18
- /** Only negotiated booleans/known empty capability markers, never agent metadata. */
18
+ export const codexContextPolicy = Object.freeze({ version: 1, scope: 'new-session', mode: 'append', content: 'text', resume: 'omit-only', changed: 'new-session-required', mapping: 'developerInstructions', nativeCliUnmodified: true });
19
+ export function supportsCodexContextPolicy(capabilities) {
20
+ const policy = capabilities._meta?.aiWorkbenchSystemPrompt;
21
+ return !!policy && typeof policy === 'object' && !Array.isArray(policy) && Object.keys(policy).length === Object.keys(codexContextPolicy).length && Object.entries(codexContextPolicy).every(([key, value]) => policy[key] === value);
22
+ }
23
+ /** Known capabilities plus the exact Codex policy whitelist; no arbitrary metadata. */
19
24
  export function recoveryCapabilities(c) {
20
- return { loadSession: c.loadSession === true, promptCapabilities: { image: c.promptCapabilities?.image === true, audio: c.promptCapabilities?.audio === true, embeddedContext: c.promptCapabilities?.embeddedContext === true }, sessionCapabilities: { ...(c.sessionCapabilities?.resume ? { resume: {} } : {}), ...(c.sessionCapabilities?.systemPrompt ? { systemPrompt: {} } : {}) } };
25
+ return { loadSession: c.loadSession === true, promptCapabilities: { image: c.promptCapabilities?.image === true, audio: c.promptCapabilities?.audio === true, embeddedContext: c.promptCapabilities?.embeddedContext === true }, sessionCapabilities: { ...(c.sessionCapabilities?.resume ? { resume: {} } : {}), ...(c.sessionCapabilities?.systemPrompt ? { systemPrompt: {} } : {}) }, ...(supportsCodexContextPolicy(c) ? { _meta: { aiWorkbenchSystemPrompt: { ...codexContextPolicy } } } : {}) };
21
26
  }
22
27
  export function recoveryKey(value) { return createHash('sha256').update(JSON.stringify(value)).digest('hex'); }
28
+ /** Preserve legacy lookup bytes; each employee endpoint scope owns a separate journal. */
29
+ export function runtimeRecoveryKey(identity, provider, sessionId, employeeScope) {
30
+ return recoveryKey([identity, provider, sessionId, ...(employeeScope ? ['employee', employeeScope] : [])]);
31
+ }
23
32
  /** History is immutable; current is atomically replaced only after fsync. No expiry. */
24
33
  export function recoveryJournal(profileDir, key) {
25
34
  if (!/^[a-f0-9]{64}$/.test(key))
@@ -18,6 +18,7 @@ export interface DetailRequest {
18
18
  provider: 'claude' | 'codex';
19
19
  identity: string;
20
20
  connection: Connection;
21
+ readonly localAcceptanceId?: string;
21
22
  }
22
23
  export declare function privateDirectory(path: string): Promise<void>;
23
24
  export declare function durableWrite(path: string, value: unknown): Promise<void>;
@@ -26,6 +27,12 @@ export declare function createRemoteDetails(options: {
26
27
  profileDir: string;
27
28
  getApi: () => RemoteDetailsApi | undefined;
28
29
  }): {
30
+ recordLocalFailure(request: {
31
+ sessionId?: string;
32
+ provider: "claude" | "codex";
33
+ code: string;
34
+ observation?: DetailObservation;
35
+ }): Promise<void>;
29
36
  recordLoginFailure(request: {
30
37
  sessionId?: string;
31
38
  code: string;
@@ -91,6 +91,12 @@ export function createRemoteDetails(options) {
91
91
  const scopes = new Map(), loginScopes = new Map();
92
92
  const initialize = async () => { await privateDirectory(join(options.profileDir, 'ai-workbench-remote-agent')); await privateDirectory(root); };
93
93
  return {
94
+ async recordLocalFailure(request) {
95
+ await initialize();
96
+ if (!/^[A-Z][A-Z0-9_]*$/.test(request.code))
97
+ throw failure('REMOTE_DETAIL_STORAGE_FAILED');
98
+ await durableWrite(join(root, randomUUID() + '.json'), { version: 1, kind: 'local-admission', code: request.code, provider: request.provider, sessionHash: request.sessionId ? hash(request.sessionId) : null, ...request.observation ? { observation: sanitizeObservation(request.observation, true) } : {} });
99
+ },
94
100
  async recordLoginFailure(request) {
95
101
  await initialize();
96
102
  const eventId = randomUUID(), diagnostic = request.diagnostic;
@@ -221,6 +227,10 @@ export function createRemoteDetails(options) {
221
227
  return { eventId, recorded: true };
222
228
  },
223
229
  async open(request) {
230
+ request = structuredClone(request);
231
+ if (request.localAcceptanceId !== undefined && (typeof request.localAcceptanceId !== 'string' || !request.localAcceptanceId.trim()))
232
+ throw failure('REMOTE_DETAIL_SCOPE_INVALID');
233
+ const localScope = request.localAcceptanceId === undefined ? undefined : Object.freeze({ localAcceptanceId: request.localAcceptanceId });
224
234
  if (!request.sessionId || !request.identity || !request.connection.instanceId || !Number.isSafeInteger(request.connection.epoch) || request.connection.epoch < 0 || !['claude', 'codex'].includes(request.provider))
225
235
  throw failure('REMOTE_DETAIL_SCOPE_INVALID');
226
236
  try {
@@ -348,7 +358,7 @@ export function createRemoteDetails(options) {
348
358
  stable();
349
359
  let response;
350
360
  try {
351
- response = await api.appendRemoteConversationDetail(structuredClone(detail));
361
+ response = await (localScope === undefined ? api.appendRemoteConversationDetail(structuredClone(detail)) : api.appendRemoteConversationDetail(structuredClone(detail), localScope));
352
362
  }
353
363
  catch {
354
364
  stable();
@@ -0,0 +1,13 @@
1
+ vscode-ripgrep
2
+
3
+ Copyright (c) Microsoft Corporation
4
+
5
+ All rights reserved.
6
+
7
+ MIT License
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,9 @@
1
+ # Bundled Mac search component
2
+
3
+ Original unmodified binaries from Microsoft @vscode/ripgrep-universal 1.18.0. The npm integrity/SHA256, per-file SHA/bytes and upstream release archives are in manifest.json. Both npm binaries were compared byte for byte with the pinned Microsoft release assets (v15.0.1). No employee download/install hook or PATH lookup.
4
+
5
+ Microsoft packaging tag v1.18.0 commit d22dec46c67fc8c5d307c9b18dba2792efd1f016 locks ripgrep-prebuilt v15.0.1 commit 67202aaafb17aecd9b5b7046d5b7baa92b05237a. Its config pins upstream ripgrep15.0.0 plus the retained Microsoft patch (Windows/ARM-musl adjustments); reported binaries are ripgrep15.0.0 with PCRE2 10.45. Upstream source: https://github.com/BurntSushi/ripgrep/tree/15.0.0 ; vendor source/config: https://github.com/microsoft/ripgrep-prebuilt/tree/v15.0.1 ; npm wrapper: https://github.com/microsoft/vscode-ripgrep/tree/v1.18.0 . Source-input hashes are retained in manifest.json. This is vendor artifact provenance, not a local reproducible build attestation; exact vendor compiler invocation/runtime std build was not independently attested.
6
+
7
+ LICENSE-vscode retains Microsoft packaging MIT text. notices/ contains ripgrep MIT/Unlicense/COPYING, PCRE2 licence, and a conservative full upstream Cargo.lock dependency superset plus Microsoft's Windows-only msvc_spectre_libs. Every crate archive matches its Cargo checksum; DEPENDENCIES.json identifies original package, version, licence and retained texts. r-efi licence is embedded in AUTHORS. wasip2 texts omitted from its crate were retrieved at its .cargo_vcs_info.json exact source commit. Superset inclusion is not a claim all non-Mac/build/test crates are linked into these Mac binaries. prepare-ripgrep-notices.py regenerates notices from the retained pinned inputs.
8
+
9
+ Runtime validates shipped rg size/SHA256, executable regular file, macOS arm64/x64 only. No strip/sign/byte alteration by X. Arm64 actual PCRE2 operation is fixture-tested; x64 is byte/inventory verified, not executed on this arm64 Mac. macOS SDK/system libraries are supplied by the OS; binaries have no Homebrew dylib dependency. The plugin message/output bound uses named acpMaxMessageBytes. Other platforms fail explicitly rather than host fallback.
Binary file
Binary file
@@ -0,0 +1,56 @@
1
+ {
2
+ "npm": "@vscode/ripgrep-universal@1.18.0",
3
+ "source": "https://registry.npmjs.org/@vscode/ripgrep-universal/-/ripgrep-universal-1.18.0.tgz",
4
+ "archiveSha256": "76a03f429dc13a90f53b60995211a54308ab4f67b2521bac00f9c4be953dff52",
5
+ "integrity": "sha512-kgrAVy1L/v/8erAjo+I720ifTf7o4rvYUwgsuEu97XAEBtPT9sk3HhcSgFpxMydvNmwdJtXo9/AVee7JjocTrg==",
6
+ "files": {
7
+ "darwin-arm64": {
8
+ "bytes": 4528512,
9
+ "sha256": "6ef40346bf31fcce79d9614c7745c198542925a0c7d4911e1ffe794c53392ac1"
10
+ },
11
+ "darwin-x64": {
12
+ "bytes": 4742676,
13
+ "sha256": "f999495980a5e6f1e7d26461ef5768b4013a62df610ed7d77a8b2de247a5b228"
14
+ }
15
+ },
16
+ "vendorRelease": "microsoft/ripgrep-prebuilt@v15.0.1",
17
+ "vendorCommit": "67202aaafb17aecd9b5b7046d5b7baa92b05237a",
18
+ "sourceRipgrep": "BurntSushi/ripgrep@15.0.0",
19
+ "reportedVersion": "ripgrep 15.0.0 / PCRE2 10.45",
20
+ "sourceInputs": [
21
+ {
22
+ "file": "vscode-build.json",
23
+ "sha256": "fcf6b245175385854a06785ae990546fe0d197ceb65ec9ca58860a5817f07abd"
24
+ },
25
+ {
26
+ "file": "vscode-binaries.lock.json",
27
+ "sha256": "0bd421f46e3ee2f127290f67e73adb240e1311162d6d33c25121849e5f2beadc"
28
+ },
29
+ {
30
+ "file": "prebuilt-config.json",
31
+ "sha256": "71bc7b3ecdd5442001f74896a738eafb3b831ee5a183e128067fe6b6d6b64ea7"
32
+ },
33
+ {
34
+ "file": "prebuilt-build-build.sh",
35
+ "sha256": "cf0d97cafca064c763d3ceeebe8b2f7647f5b4b35710b37c74804a4d3e1b3929"
36
+ },
37
+ {
38
+ "file": "prebuilt-patches-0001-resolve-binskim-issues.patch",
39
+ "sha256": "45f8b58bba714c446de407f93120f557736b45fad6f43ea283077201646a1be7"
40
+ },
41
+ {
42
+ "file": "ripgrep-lock",
43
+ "sha256": "257bfa1eeacfa4d8222e2c50f9d2f8d15ef07e96adee46eaa87839f3b6cfa3b4"
44
+ }
45
+ ],
46
+ "vendorArchives": {
47
+ "darwin-arm64": {
48
+ "sha256": "2fa16464fd8638588a67c7fc172d3c4b57fbdc65dff366e10b0b0e90734628a6",
49
+ "url": "https://github.com/microsoft/ripgrep-prebuilt/releases/download/v15.0.1/ripgrep-v15.0.1-aarch64-apple-darwin.tar.gz"
50
+ },
51
+ "darwin-x64": {
52
+ "sha256": "591c693e80bb444ef1907b2a906feb9c77bcafe1cdf509107cc75dcf0e875bd2",
53
+ "url": "https://github.com/microsoft/ripgrep-prebuilt/releases/download/v15.0.1/ripgrep-v15.0.1-x86_64-apple-darwin.tar.gz"
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,3 @@
1
+ This project is dual-licensed under the Unlicense and MIT licenses.
2
+
3
+ You may use this code under the terms of either license.