dsh-use-codex 0.3.0 → 0.4.1

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.en.md CHANGED
@@ -262,6 +262,16 @@ Reports:
262
262
  - timeout and output limits
263
263
  - a summary of the most recent run in the current DSH process
264
264
 
265
+ ### `codex_danger`
266
+
267
+ Runtime toggle for `danger-full-access` (effective when the host config sets `allowDangerFullAccess: true`).
268
+
269
+ | Param | Type | Required | Description |
270
+ |---|---|---|---|
271
+ | `enabled` | `boolean` | yes | `true` enables danger mode (default sandbox becomes `danger-full-access`), `false` disables it (back to `workspace-write`) |
272
+
273
+ When enabled, the **next** `codex_run` defaults to `danger-full-access` (no sandbox: unrestricted read/write, network access, arbitrary commands). This only changes the default; an explicit `sandbox` argument is untouched. The state persists across DSH restarts.
274
+
265
275
  ### `codex_switch`
266
276
 
267
277
  | Argument | Type | Required | Description |
package/README.md CHANGED
@@ -29,11 +29,11 @@
29
29
  ## 功能特性
30
30
 
31
31
  - **自然语言委派**:在 DSH 中说“让 Codex 做……”或“交给 Codex 执行……”。
32
- - **三个内置工具**:任务执行、状态检查、即时开关。
32
+ - **四个内置工具**:任务执行、状态检查、危险模式开关、即时启停开关。
33
33
  - **工作目录白名单**:只允许 Codex 在显式授权的真实目录中运行。
34
34
  - **软链逃逸防护**:同时解析工作目录与白名单的真实路径。
35
35
  - **默认安全沙箱**:默认使用 Codex 的 `workspace-write` 模式。
36
- - **危险模式双重授权**:`danger-full-access` 必须由宿主配置显式允许。
36
+ - **危险模式双重授权**:`danger-full-access` 必须由宿主配置 `allowDangerFullAccess: true` 允许,再由 `codex_danger` 运行时开关打开。
37
37
  - **无 shell 拼接**:任务正文作为单个 argv 参数传递,避免 shell 注入。
38
38
  - **进程组清理**:超时或取消时终止完整 Codex 进程组。
39
39
  - **输出限长**:限制 stdout/stderr,避免单次结果淹没会话。
@@ -248,7 +248,12 @@ DSH 的模型会按需调用 `codex_run`。任务应写清目标、范围、约
248
248
  | `sandbox` | `string` | 否 | `read-only`、`workspace-write` 或 `danger-full-access` |
249
249
  | `timeoutSec` | `number` | 否 | 本次超时,不能超过插件配置的 `timeoutSec` |
250
250
 
251
- 默认沙箱为 `workspace-write`。`danger-full-access` 默认拒绝,只有在宿主配置中设置 `allowDangerFullAccess: true` 后才可选择。
251
+ 默认沙箱由两层开关共同决定:
252
+
253
+ 1. **宿主配置** `allowDangerFullAccess: true|false`(profile 补丁,重启生效)——这是硬性许可,`false` 时任何方式都无法使用 `danger-full-access`
254
+ 2. **运行时开关** `codex_danger`(即时生效,持久化到状态文件)——宿主允许后,用它切换"默认沙箱"是 `danger-full-access` 还是 `workspace-write`
255
+
256
+ 省略 `sandbox` 参数时:宿主允许且 `codex_danger` 处于打开状态 → `danger-full-access`;否则 → `workspace-write`。显式传入的 `sandbox` 始终优先于默认值。
252
257
 
253
258
  ### `codex_status`
254
259
 
@@ -262,6 +267,16 @@ DSH 的模型会按需调用 `codex_run`。任务应写清目标、范围、约
262
267
  - 超时与输出限制
263
268
  - 当前 DSH 进程内最近一次调用的结果摘要
264
269
 
270
+ ### `codex_danger`
271
+
272
+ 切换 `danger-full-access` 的运行时开关(宿主 `allowDangerFullAccess: true` 时有效)。
273
+
274
+ | 参数 | 类型 | 必填 | 说明 |
275
+ |---|---|---|---|
276
+ | `enabled` | `boolean` | 是 | `true` 打开危险模式(默认沙箱变 `danger-full-access`),`false` 关闭(回到 `workspace-write`) |
277
+
278
+ 打开后**下一次** `codex_run` 默认以 `danger-full-access` 运行(无沙箱:可读写任意路径、访问网络、执行任意命令)。此开关只影响默认沙箱,不影响显式传入的 `sandbox` 参数。状态持久化,重启 DSH 后保留。
279
+
265
280
  ### `codex_switch`
266
281
 
267
282
  | 参数 | 类型 | 必填 | 说明 |
package/lib/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 安全边界:
5
5
  * 1. 工作目录必须是白名单内的真实绝对路径;软链逃逸会被拒绝。
6
- * 2. 默认使用 workspace-write,危险模式需由宿主配置显式开启。
6
+ * 2. 沙箱默认 workspace-write;宿主配置 allowDangerFullAccess 后可用 codex_danger 运行时开关切到 danger-full-access。
7
7
  * 3. 不经过 shell,任务作为单个 argv 传给 Codex。
8
8
  * 4. 超时或取消时终止 Codex 进程组,并限制输出大小。
9
9
  * 5. 不持久化任务正文、工作目录或输出;状态文件只记录即时开关。
@@ -220,6 +220,31 @@ function textTool({ name: toolName, description, parameters, timeoutMs, execute
220
220
  };
221
221
  }
222
222
 
223
+ /** Settings-page schema builder; returns null when schemastery is unavailable. */
224
+ let _Config = null;
225
+ try {
226
+ const { default: z } = await import('@deepseek-ai/schemastery');
227
+ _Config = z.object({
228
+ enabled: z.boolean().default(true)
229
+ .description('启动时是否注册 Codex 委派工具(改为 false 并重启可完全停用)。'),
230
+ bin: z.string().default('codex')
231
+ .description('Codex CLI 可执行文件路径;留空用 PATH 中的 codex。'),
232
+ defaultCwd: z.string().default('')
233
+ .description('默认工作目录;留空用 DSH 进程当前目录。'),
234
+ allowedRoots: z.array(z.string()).role('textarea').default([])
235
+ .description('允许 Codex 工作的目录白名单,每行一个绝对路径。'),
236
+ allowDangerFullAccess: z.boolean().default(false)
237
+ .description('完全权限总许可:开启后可用 codex_danger 开关让 codex_run 默认以 danger-full-access(无沙箱)运行。关闭则任何方式都无法使用危险模式。'),
238
+ timeoutSec: z.number().min(1).max(3600).step(1).default(900)
239
+ .description('单次任务超时上限(秒)。'),
240
+ maxOutputChars: z.number().min(1000).max(200000).step(500).default(20000)
241
+ .description('返回输出的最大字符数。'),
242
+ }).description('Codex 委派');
243
+ } catch {}
244
+
245
+ /** DSH settings UI renders this panel; null schema = no settings page. */
246
+ export const Config = _Config;
247
+
223
248
  export function apply(ctx, config = {}) {
224
249
  if (config.enabled === false) {
225
250
  ctx.logger?.info?.('[use-codex] disabled by configuration');
@@ -266,6 +291,13 @@ export function apply(ctx, config = {}) {
266
291
  }
267
292
 
268
293
  const enabledNow = () => readState().enabled !== false;
294
+ // Runtime danger-mode switch: defaults to the host config; codex_danger toggles it per session.
295
+ const dangerNow = () => {
296
+ const state = readState();
297
+ if (typeof state.dangerFullAccess === 'boolean') return state.dangerFullAccess;
298
+ return allowDanger;
299
+ };
300
+ const defaultSandbox = () => (dangerNow() ? 'danger-full-access' : 'workspace-write');
269
301
  let lastRun = null;
270
302
 
271
303
  const resolveRunCwd = (input) => {
@@ -287,7 +319,7 @@ export function apply(ctx, config = {}) {
287
319
  description:
288
320
  '让本机 OpenAI Codex CLI 执行一段独立任务并返回结果。'
289
321
  + '当用户说“让 Codex 做……”“交给 Codex 执行……”,或希望把编码、排障、批量文件处理任务委派出去时调用。'
290
- + '工作目录必须在 DSH 配置的白名单内;默认使用 workspace-write 沙箱;失败时如实返回失败原因。',
322
+ + '工作目录必须在 DSH 配置的白名单内;默认沙箱由宿主配置与运行时开关共同决定;失败时如实返回失败原因。',
291
323
  parameters: {
292
324
  type: 'object',
293
325
  additionalProperties: false,
@@ -305,7 +337,7 @@ export function apply(ctx, config = {}) {
305
337
  sandbox: {
306
338
  type: 'string',
307
339
  enum: ['read-only', 'workspace-write', 'danger-full-access'],
308
- description: 'Codex 沙箱模式,默认 workspace-write;danger-full-access 需宿主配置显式允许。',
340
+ description: 'Codex 沙箱模式;省略时用 defaultSandbox()(宿主 allowDangerFullAccess 与 codex_danger 运行时开关共同决定)。',
309
341
  },
310
342
  timeoutSec: {
311
343
  type: 'number',
@@ -324,13 +356,16 @@ export function apply(ctx, config = {}) {
324
356
  if (!task) return '❌ 任务不能为空。';
325
357
  if (task.length > MAX_TASK_CHARS) return `❌ 任务过长,最多 ${MAX_TASK_CHARS} 字符。`;
326
358
 
327
- const sandbox = String(args?.sandbox || 'workspace-write');
359
+ const sandbox = String(args?.sandbox || defaultSandbox());
328
360
  if (!['read-only', 'workspace-write', 'danger-full-access'].includes(sandbox)) {
329
361
  return `❌ 不支持的沙箱模式:${sandbox}`;
330
362
  }
331
363
  if (sandbox === 'danger-full-access' && !allowDanger) {
332
364
  return '❌ danger-full-access 未获宿主配置许可,拒绝执行。';
333
365
  }
366
+ if (sandbox === 'danger-full-access' && !dangerNow()) {
367
+ return '🛡 danger-full-access 已被 codex_danger 关闭;请先用 codex_danger 打开,或显式传 workspace-write。';
368
+ }
334
369
 
335
370
  let cwd;
336
371
  try {
@@ -412,7 +447,7 @@ export function apply(ctx, config = {}) {
412
447
  `📦 Codex:${version.ok ? version.stdout : `不可用(${version.error || version.stderr || version.code})`}`,
413
448
  `🔑 认证:${login.stdout || login.stderr || (login.ok ? '未知' : login.code)}`,
414
449
  `📁 白名单:${allowedRoots.length ? allowedRoots.join('、') : '(空)'}`,
415
- `🛡 危险模式:${allowDanger ? '允许(危险)' : '禁止'}`,
450
+ `🛡 危险模式:${allowDanger ? (dangerNow() ? '允许且当前打开' : '允许但当前关闭') : '禁止'}`,
416
451
  `⏱ 超时上限:${maxTimeoutSec}s`,
417
452
  `📏 输出上限:${maxOutputChars} 字符`,
418
453
  ];
@@ -424,6 +459,38 @@ export function apply(ctx, config = {}) {
424
459
  },
425
460
  }),
426
461
 
462
+ textTool({
463
+ name: 'codex_danger',
464
+ description: '切换 danger-full-access 运行时开关。'
465
+ + '仅在宿主配置 allowDangerFullAccess: true 时有效;'
466
+ + '打开后 codex_run 默认使用 danger-full-access(无沙箱),关闭则回到 workspace-write。'
467
+ + '此开关影响下一次 codex_run 的默认沙箱,不影响显式传入的 sandbox 参数。',
468
+ parameters: {
469
+ type: 'object',
470
+ additionalProperties: false,
471
+ properties: {
472
+ enabled: {
473
+ type: 'boolean',
474
+ description: 'true 为打开危险模式(默认沙箱变 danger-full-access),false 为关闭(回到 workspace-write)。',
475
+ },
476
+ },
477
+ required: ['enabled'],
478
+ },
479
+ timeoutMs: 10_000,
480
+ async execute(args) {
481
+ if (!allowDanger) {
482
+ return '❌ 宿主配置未开启 allowDangerFullAccess,此开关无效。';
483
+ }
484
+ const danger = args?.enabled === true;
485
+ if (!writeState({ dangerFullAccess: danger })) {
486
+ return '❌ 无法写入 Codex 危险模式状态,请检查 DSH 状态目录权限。';
487
+ }
488
+ return danger
489
+ ? '🔓 危险模式已打开:codex_run 默认沙箱为 danger-full-access。'
490
+ : '🛡 危险模式已关闭:codex_run 默认沙箱为 workspace-write。';
491
+ },
492
+ }),
493
+
427
494
  textTool({
428
495
  name: 'codex_switch',
429
496
  description: '即时打开或关闭 Codex 委派,不需要重启 DSH;关闭后 codex_run 会拒绝执行。',
@@ -458,7 +525,7 @@ export function apply(ctx, config = {}) {
458
525
  }
459
526
  }
460
527
 
461
- ctx.logger?.info?.(`[use-codex] registered ${tools.length} tools; allowed roots=${allowedRoots.length}; enabled=${enabledNow()}`);
528
+ ctx.logger?.info?.(`[use-codex] registered ${tools.length} tools; allowed roots=${allowedRoots.length}; enabled=${enabledNow()}; danger=${dangerNow()}`);
462
529
  }
463
530
 
464
531
  export default { name, inject, apply };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "dsh-use-codex",
3
3
  "displayName": "DSH Use Codex",
4
- "description": "通过 DeepSeek Harness 工具调用本机 Codex CLI 执行独立任务。",
5
- "version": "0.3.0",
4
+ "description": "通过 DeepSeek Harness 工具调用本机 Codex CLI 执行独立任务;danger-full-access 支持宿主许可 + 运行时开关双重授权。",
5
+ "version": "0.4.1",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
8
8
  "exports": {
@@ -52,5 +52,8 @@
52
52
  "homepage": "https://github.com/chaorenzeng/dsh-use-codex#readme",
53
53
  "bugs": {
54
54
  "url": "https://github.com/chaorenzeng/dsh-use-codex/issues"
55
+ },
56
+ "dependencies": {
57
+ "@deepseek-ai/schemastery": "^3.18.4"
55
58
  }
56
59
  }