ai_co_discuss 0.2.12 → 0.2.13

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.
@@ -65,6 +65,8 @@ description: "AI CoDiscuss 的主持技能,仅主持人调用,且须同时
65
65
  | 已可收束,或正在限时收束 | 先发表有原文依据的最终 `moderation`、保存 state 与简报,最后设为 `concluded`。 |
66
66
  | 缺少必要用户决定或无法继续 | 保留已有判断与具体阻碍,用 `execution fail` 暂停,向用户说明需要什么。 |
67
67
 
68
+ 后续若干次安排的专家与问题可预先确定时(如固定轮流报数,不是只排“本轮三位成员”),一次用 `turn create --plan-file` 排满整个可预知序列(最多 10 项),不要每答完一位就唤醒主持再排下一位;只有后一位必须读前一位回答才能决定时才逐个安排。创建安排或收束成功后立即结束,只回一句话,不再输出总结。
69
+
68
70
  创建安排、完成收束或执行失败会结束本次写入资格;此后只允许回读核验,不再补 state、回执或归还已交接的发言权。是否完成以网站业务结果为准;结果不明按参与技能核对原提交,不另创安排。
69
71
 
70
72
  ## 保存有用的进度
@@ -60,7 +60,7 @@ description: "AI CoDiscuss 的通用参与技能,所有参与者(包括主
60
60
 
61
61
  ## 保存真实结果
62
62
 
63
- 观点用 `message post`,摘要用 `--summary` / `--summary-file`,完整正文优先 UTF-8 `--body-file`;自己的观点署名自己。主持消息用 `moderation`。代发保留真实作者、完整原文及引用关系,摘要归实际撰写者,不把自己的改写冒充对方回答。
63
+ 观点用 `message post`。讨论房间的专家观点用 `--kind opinion`,主持发言用 `--kind moderation` 且不带 `--summary`;`chat` 仅用于自由协作房间。观点摘要用 `--summary` / `--summary-file`,完整正文优先 UTF-8 `--body-file`;自己的观点署名自己。代发保留真实作者、完整原文及引用关系,摘要归实际撰写者,不把自己的改写冒充对方回答。
64
64
 
65
65
  需要提交原文件时,先 `attachment upload ROOM --as 本人 --file FILE --submission-id 上传编号`,再把回执中的附件 ID 通过 `message post --attachment ID` 关联,可重复指定(最多 10 个,单个 20 MiB)。受保护上传带本次 `--access-file`,须在回答完成、执行资格结束前上传。上传和消息分别保存提交编号;结果不明用 `attachment list ROOM --submission-id 上传编号` 核对,重试沿用原文件与原编号。
66
66
 
package/docs/runner.md CHANGED
@@ -228,7 +228,9 @@ Windows 的 `executable` 填原生 `.exe`,不填 npm 的 `.cmd` / `.ps1` 包
228
228
 
229
229
  进度看板的参与者姓名下显示本场已登记的模型与思考强度,不使用新建草稿或本机默认配置代替。由本机桥接的只读 `room-models` 返回 `adapter/model/effort`,按当前站点与房间匹配;本机页面和已授权连接的线上页面均可读取,不要求暂停或浏览器持有房间控制凭据,不返回路径、令牌或会话编号。CLI 未显式指定时显示“默认模型 / 默认强度”,agy 显示“强度随模型”,App 和手动参与提示在原软件内设置;未连接本机、未登记或旧版服务不支持时显示未获取。它展示启动配置,不能证明软件最终采用的默认值,也不提供讨论中改模型的入口。
230
230
 
231
- 两种新适配器都不需要 `source_thread_id` 或 `ipc_directory`。实际 ID 在输出流到达时写入本机绑定和本次执行凭据,随后由接入程序在会话启动时直接 `execution enter`(`codex_cli` 与 `claude`,任务内容内联进提示词,省去模型读文件和进入的往返;其余适配器仍由 AI 自行进入),AI 通过讨论 CLI 保存业务结果;Codex CLI 输出 `turn.completed` 1.5 秒后若进程未退出即终止,避免同会话的下一次投递等待收尾。每次执行在任务目录写 `event-ID.trace.jsonl`(时间戳加阶段:`event_seen`、`blocked_by_running_process`、`reserve_*`、`permission_check_*`、`cli_spawned`、`enter_*`、Codex 的 `thread.started` / `turn.started` / 工具命令 / `turn.completed`、`kill_after_completed`、`cli_closed`),仅用于定位各阶段耗时,不含凭据;程序不把终端回答直接代发。Codex App / CLI 可通过上述暂停后配置修正保留原绑定切换;其他适配器或项目、会话变更仍须使用独立 `data_directory` 明确重新接入。此路径不承诺 CLI 会话自动出现在桌面 App 的项目列表。
231
+ 两种新适配器都不需要 `source_thread_id` 或 `ipc_directory`。实际 ID 在输出流到达时写入本机绑定和本次执行凭据,随后由接入程序在会话启动时直接 `execution enter`(`codex_cli`、`claude` 与 `antigravity_cli`,任务内容内联进提示词,省去模型读文件和进入的往返;其余适配器仍由 AI 自行进入),AI 通过讨论 CLI 保存业务结果;Codex CLI 输出 `turn.completed` 1.5 秒后若进程未退出即终止,避免同会话的下一次投递等待收尾。每次执行在任务目录写 `event-ID.trace.jsonl`(时间戳加阶段:`event_seen`、`blocked_by_running_process`、`reserve_*`、`permission_check_*`、`cli_spawned`、`enter_*`、Codex 的 `thread.started` / `turn.started` / 工具命令 / `turn.completed`、`kill_after_completed`、`cli_closed`),仅用于定位各阶段耗时,不含凭据;程序不把终端回答直接代发。Codex App / CLI 可通过上述暂停后配置修正保留原绑定切换;其他适配器或项目、会话变更仍须使用独立 `data_directory` 明确重新接入。此路径不承诺 CLI 会话自动出现在桌面 App 的项目列表。
232
+
233
+ trace 中 `event_seen.event_created_at` 记录服务端事件创建时间,`t` 仍为本机记录该阶段的实际时间,两者分别用于核对事件创建后的等待和本机阶段耗时。
232
234
 
233
235
  `codex_cli` 的 `exec resume` 需要取得该会话的写入权;已有聊天仍被 Codex App 或另一进程持有时,会报 `thread-store conflict / already has an active writer`,App 显示空闲也不代表已释放。重复重试或仅关闭窗口不能保证解除占用。需要沿用 App 原聊天时,暂停后在本场接入设置中切到 `codex`,由 `codex queue` 向原聊天交付;需要独立 CLI 时,使用未被占用的 CLI 会话或新建讨论时省略会话 ID。接入程序保留这一根因,不让后续模型列表刷新超时覆盖它,也不自动换会话或切换适配器。
234
236
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai_co_discuss",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
4
4
  "bin": {
5
5
  "codiscuss": "runner/codiscuss.mjs"
6
6
  },
@@ -391,7 +391,8 @@ function trace_cli_event(event, task) {
391
391
  if (!task.on_trace) return;
392
392
  const item = event.item;
393
393
  const command = item?.command ? String(item.command).replace(/^.*?-Command\s+/, '').slice(0, 100) : '';
394
- task.on_trace(item ? `${event.type}:${item.type}` : event.type, command ? { command } : {});
394
+ const type = event.type ?? event.event ?? 'unknown';
395
+ task.on_trace(item ? `${type}:${item.type}` : type, command ? { command } : {});
395
396
  }
396
397
 
397
398
  /** Keep the actual resume failure even when later model-refresh logs replace the diagnostic tail. */
@@ -10,7 +10,7 @@ import { atomic_json, deliver_task, remove_agy_projects, setup_sidecar, sidecar_
10
10
 
11
11
  const POLL_MS = 2000;
12
12
  /** Headless CLIs know their session at start, so the runner enters the execution instead of spending model turns on it. */
13
- const AUTO_ENTER_ADAPTERS = new Set(['codex_cli', 'claude']);
13
+ const AUTO_ENTER_ADAPTERS = new Set(['codex_cli', 'claude', 'antigravity_cli']);
14
14
  const DELIVERY_RETRY_DELAYS_MS = [2000, 4000];
15
15
  const RENEW_MS = 30_000;
16
16
  const ADAPTER_NAMES = ['codex', 'claude', 'antigravity', 'codex_cli', 'antigravity_cli'];
@@ -180,7 +180,7 @@ export function task_files(config, event, token, binding) {
180
180
  draft_directory,
181
181
  role: event.role, turn_id: event.turn_id, skills, cli, subcommands: TASK_SUBCOMMANDS, access_file: access_path,
182
182
  instructions: `读取指定技能;网站命令只用 ${cli} 的 subcommands 子命令,命令以 ${cli} 开头,不用 python discuss.py、cd、管道或其他入口;${auto_enter ? '接入程序已进入本次执行,不要再执行 execution enter。' : `使用 ${cli} execution enter 房间 执行编号 --access-file 凭据路径 进入。进入成功后才处理本次安排;`}凭据文件由 CLI 内部读取,不要打印或读取其 token。每次业务写入都带 --access-file。答案草稿只保存到 draft_directory,不修改任务、凭据、日志或调度数据库;${project_rule}只处理本次工作,不建定时任务。主持创建下一安排或收束即结束,专家提交原文后结束。无效或已进入的任务不要重复执行。` });
183
- const scope = `本次只放行任务内 subcommands 列出的 ${cli} 子命令,命令以 ${cli} 开头,不用 python discuss.py、cd、管道或其他入口。任务内 cwd 是讨论项目目录;${project_rule}项目读写仍受软件实际权限和议题授权约束。不读取凭据内容。`;
183
+ const scope = `本次只放行任务内 subcommands 列出的 ${cli} 子命令,命令以 ${cli} 开头,不用 python discuss.py、cd、管道或其他入口。任务内 cwd 是讨论项目目录;${project_rule}项目读写仍受软件实际权限和议题授权约束。不读取凭据内容。读取含中文的技能或文本文件时用 rg --encoding utf-8 . 文件路径,不用 Get-Content(Windows PowerShell 会按系统编码读出乱码,需要反复重试)。`;
184
184
  const intro = `用户已启动此房间的全自动讨论。请以 ${event.participant} 的${event.role === 'host' ? '主持' : '专家'}职责处理本次工作。`;
185
185
  const prompt = auto_enter
186
186
  ? `${intro}接入程序已为本次执行完成 execution enter,不要再执行。任务内容如下(同一份保存在 ${task_path},无需再读):
@@ -225,6 +225,7 @@ export class DiscussionRunner {
225
225
  const attempts = row.attempts + 1;
226
226
  this.store.record(row.id, { status: 'dispatching', sent_at: Date.now(), attempts, error: '', retry_at: 0 });
227
227
  let invoked = false;
228
+ let entered = false;
228
229
  try {
229
230
  const task = task_files(this.config, event, row.token, binding);
230
231
  invoked = true;
@@ -232,7 +233,8 @@ export class DiscussionRunner {
232
233
  on_trace: (stage, detail) => this.trace(row.id, stage, detail),
233
234
  on_binding: session => {
234
235
  this.store.bind(event.participant, session);
235
- if (AUTO_ENTER_ADAPTERS.has(adapter.adapter)) this.enter(row, session);
236
+ // agy reports its session again in the result event; enter only once.
237
+ if (AUTO_ENTER_ADAPTERS.has(adapter.adapter) && !entered) { entered = true; this.enter(row, session); }
236
238
  },
237
239
  on_process: child => this.track(event.participant, child),
238
240
  on_output: (path, chunk) => appendFileSync(path, chunk, { mode: 0o600 }),
@@ -347,7 +349,7 @@ export class DiscussionRunner {
347
349
  for (const { row, event } of pending) {
348
350
  if (event.generation !== run.generation || event.run_id !== run.run_id) this.store.record(row.id, { status: 'cancelled' });
349
351
  }
350
- for (const { row } of pending) if (!this.seen.has(row.id)) { this.seen.add(row.id); this.trace(row.id, 'event_seen'); }
352
+ for (const { row, event } of pending) if (!this.seen.has(row.id)) { this.seen.add(row.id); this.trace(row.id, 'event_seen', { event_created_at: event.created_at }); }
351
353
  const next = eligible.at(-1);
352
354
  if (next && this.running.get(next.event.participant) && !this.blocked.has(next.row.id)) {
353
355
  this.blocked.add(next.row.id);
@@ -283,7 +283,7 @@ function setup_issues(result) {
283
283
  /** Ask before restarting a running website; non-interactive runs never stop it and report the pending restart instead. */
284
284
  async function confirm_restart(reason, options) {
285
285
  if (options.yes || !process.stdin.isTTY) return false;
286
- const choice = await ask(`${reason}\n重启后生效,重启会暂停托管中的讨论。现在重启?`, '[重启/暂不,默认重启]');
286
+ const choice = await ask(`${reason}\n重启后生效,重启会暂停托管中的讨论。现在重启?`, '[Y/N,默认 Y]');
287
287
  return !choice.trim() || ['重启', 'restart', 'r', 'y', 'yes'].includes(choice.trim().toLowerCase());
288
288
  }
289
289