ai_co_discuss 0.3.5 → 0.3.6

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/docs/en/runner.md CHANGED
@@ -67,7 +67,7 @@ Choose a provider and enter a key under **Smart Scheduling** (智能调度) when
67
67
 
68
68
  ## Permissions
69
69
 
70
- Project file access is set per member and is read-only by default. Agents can only run the `codiscuss` commands that read and write rooms. How strictly this is enforced depends on the tool: Codex uses its native sandbox, `agy` uses dedicated project permission rules, and permissions you have already granted in Claude Code still apply.
70
+ Permissions are set per automatically started CLI member and default to read-only. The four levels are read-only, writable, automatic approval, and unrestricted; unsupported levels are disabled (`agy` does not support automatic approval in the background). Read-only pre-approves room-related `codiscuss` commands and answer drafts; writable allows project edits and commands. Automatic approval delegates decisions to the tool, while unrestricted skips permission prompts. Hover over a level for its exact scope. Codex uses its native sandbox, `agy` uses dedicated project rules, and existing Claude Code grants still apply. Manually started members keep their session's own permissions.
71
71
 
72
72
  ## Local Service
73
73
 
package/docs/runner.md CHANGED
@@ -69,7 +69,7 @@ API 成员可以担任专家或主持人,只有房间读写工具,不访问
69
69
 
70
70
  ## 权限
71
71
 
72
- 项目文件权限按成员设置,默认只读。AI 只能运行读写房间的 `codiscuss` 命令。限制强度取决于各软件:Codex 使用原生沙箱,agy 使用独立的项目权限规则,Claude Code 中你已有的授权仍然生效。
72
+ 项目权限按程序启动的 CLI 成员设置,默认只读;可选只读、可写、自动、全放开,软件不支持的档位灰显(agy 后台不支持自动)。只读档预先放行读写房间的 `codiscuss` 命令和答案草稿,可写档允许修改项目、运行命令;自动档由软件审核操作,全放开跳过权限确认。具体范围见档位的悬停说明。Codex 使用原生沙箱,agy 使用独立项目规则,Claude Code 中你已有的授权仍然生效;手动启动成员的权限沿用原会话设置。
73
73
 
74
74
  ## 常驻讨论服务
75
75
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai_co_discuss",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "bin": {
5
5
  "codiscuss": "runner/codiscuss.mjs"
6
6
  },
@@ -256,7 +256,7 @@ function agy_project_grants(config, task, resources, user_home) {
256
256
  throw new Error('agy 草稿目录不能位于只读项目、运行目录、技能或 .gemini 配置目录中,未交付讨论任务');
257
257
  }
258
258
  const write_rule = directory => `write_file(${resolve(directory).replaceAll('\\', '/')})`;
259
- // 全放开 also runs commands outside agy's sandbox and allows MCP tools; run data stays protected at every level.
259
+ // 全放开 also allows commands outside agy's sandbox and MCP tools; deny rules are still written, but bypass may override them.
260
260
  const full = config.project_access === 'full';
261
261
  return { allow: [agy_rule(), write_rule(task.draft_directory),
262
262
  ...(config.project_access === 'read' ? [] : [...projects.map(write_rule), 'command(*)']), ...(full ? ['unsandboxed_command(*)'] : []),
@@ -727,7 +727,10 @@ function cli_invocation(config, binding, task, user_home) {
727
727
  const project = config.session_id ? null : prepare_agy_project(config, binding, task, user_home);
728
728
  const args = ['--output-format', 'stream-json', '--print-timeout', '0', '--add-dir', task.directory,
729
729
  '--add-dir', task.draft_directory, '--add-dir', task.skills_directory];
730
- args.push('--mode', 'accept-edits', ...(project ? ['--project', project.project_id] : []));
730
+ // Headless agy refuses `--mode auto` ("not available for this account", 1.4.10–1.4.11) though its interactive window
731
+ // offers it; 全放开 uses the flag its own denial message suggests on top of the open project grants.
732
+ args.push('--mode', 'accept-edits', ...(config.project_access === 'full' ? ['--dangerously-skip-permissions'] : []),
733
+ ...(project ? ['--project', project.project_id] : []));
731
734
  if (binding.session_id) args.push('--conversation', binding.session_id);
732
735
  if (config.model) args.push('--model', config.model);
733
736
  if (config.effort) args.push('--effort', config.effort);
@@ -3,7 +3,7 @@ import { spawn } from 'node:child_process';
3
3
  import { createHash, randomUUID } from 'node:crypto';
4
4
  import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, statSync } from 'node:fs';
5
5
  import { homedir } from 'node:os';
6
- import { dirname, isAbsolute, join, resolve } from 'node:path';
6
+ import { dirname, isAbsolute, join, posix, resolve, win32 } from 'node:path';
7
7
  import { DatabaseSync } from 'node:sqlite';
8
8
  import { setTimeout as sleep } from 'node:timers/promises';
9
9
  import { pathToFileURL } from 'node:url';
@@ -210,7 +210,9 @@ export function pick_directory({ platform = process.platform, spawn_process = sp
210
210
  child.once('error', () => reject(new Error('无法打开目录选择窗口,请直接输入完整路径')));
211
211
  child.once('close', code => {
212
212
  const path = output.trim();
213
- resolve_result(code === 0 && isAbsolute(path) ? { path } : { cancelled: true });
213
+ // Judge the path by the picker's platform, not the host's: a Windows path is not absolute on POSIX.
214
+ const absolute = platform === 'win32' ? win32.isAbsolute(path) : posix.isAbsolute(path);
215
+ resolve_result(code === 0 && absolute ? { path } : { cancelled: true });
214
216
  });
215
217
  });
216
218
  }
@@ -58,17 +58,23 @@ const ACCESS_HINTS = {
58
58
  codex_cli: { read: '只读沙箱', write: '项目可写的沙箱,命令在沙箱内运行、可联网',
59
59
  auto: '沙箱外的操作由模型申请提权,Codex 自动审核代替人工批准', full: '无沙箱、无审批(--dangerously-bypass-approvals-and-sandbox)' },
60
60
  antigravity_cli: { read: '只放行网站命令;碰到未放行的命令会直接结束本轮', write: '可写项目,命令全部放行(在 agy 沙箱内)',
61
- full: '再放开沙箱外命令与 MCP 工具' },
61
+ full: '跳过全部权限确认(--dangerously-skip-permissions),并放开沙箱外命令与 MCP 工具' },
62
62
  };
63
63
 
64
- /** agy has no automatic mode headless ("not available for this account", tested 1.4.10), so it offers no 自动. */
64
+ /** agy offers 自动 only in its interactive window; headless `--mode auto` is "not available for this account" (1.4.10–1.4.11). */
65
65
  export function access_levels(adapter) {
66
66
  return adapter === 'antigravity_cli' ? PROJECT_ACCESS.filter(level => level !== 'auto') : PROJECT_ACCESS;
67
67
  }
68
68
 
69
- /** The levels a software supports, labelled for the page, with what each does there on hover. */
69
+ // Why a level a software lacks is shown but disabled, so every CLI card lines up the same four levels.
70
+ const UNSUPPORTED_HINTS = { antigravity_cli: { auto: 'agy 只在交互窗口提供自动模式,后台运行(-p)不支持' } };
71
+
72
+ /** All four levels labelled for the page, with what each does in this software on hover; ones it lacks are disabled. */
70
73
  export function access_options(adapter) {
71
- return access_levels(adapter).map(value => ({ value, label: ACCESS_LABELS[value], hint: ACCESS_HINTS[adapter]?.[value] || '' }));
74
+ const levels = access_levels(adapter);
75
+ return PROJECT_ACCESS.map(value => levels.includes(value)
76
+ ? { value, label: ACCESS_LABELS[value], hint: ACCESS_HINTS[adapter]?.[value] || '' }
77
+ : { value, label: ACCESS_LABELS[value], hint: UNSUPPORTED_HINTS[adapter]?.[value] || '该软件不支持此档位', disabled: true });
72
78
  }
73
79
 
74
80
  /** The page's name for a level; `own` reads as decided by the member's own session. */
package/web/app.js CHANGED
@@ -2458,12 +2458,11 @@ function launch_access(name) {
2458
2458
  /** Classic select options; an empty value inherits the launch-wide setting. */
2459
2459
  const ACCESS_LABELS = { read: "只读", write: "可写", auto: "自动", full: "完全放开" };
2460
2460
 
2461
- // Mirrors access_options in runner/expert_prompts.mjs; agy has no headless 自动, and the shared setting stays 只读 / 可写.
2461
+ // Mirrors access_options in runner/expert_prompts.mjs; agy shows 自动 disabled (no headless auto), and the shared setting stays 只读 / 可写.
2462
2462
  function access_options(value = "", inherit = "", adapter = "") {
2463
- const levels = !inherit ? [["read", "只读"], ["write", "可写"]]
2464
- : [["read", "只读"], ["write", "可写"], ...(adapter === "antigravity_cli" ? [] : [["auto", "自动"]]), ["full", "完全放开"]];
2463
+ const levels = !inherit ? [["read", "只读"], ["write", "可写"]] : [["read", "只读"], ["write", "可写"], ["auto", "自动"], ["full", "全放开"]];
2465
2464
  const options = [...(inherit ? [["", inherit]] : []), ...levels];
2466
- return options.map(([key, label]) => `<option value="${key}" ${(value || (inherit ? "" : "read")) === key ? "selected" : ""}>${label}</option>`).join("");
2465
+ return options.map(([key, label]) => `<option value="${key}" ${(value || (inherit ? "" : "read")) === key ? "selected" : ""}${key === "auto" && adapter === "antigravity_cli" ? " disabled" : ""}>${label}</option>`).join("");
2467
2466
  }
2468
2467
 
2469
2468
  /** Refresh classic readbacks without replacing the input currently being edited. */