ai_co_discuss 0.2.84 → 0.2.86

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/web/app.js CHANGED
@@ -1098,15 +1098,20 @@ async function describe_member(name, text) {
1098
1098
  /** Switch a woken member's project files between read-only and writable; the local service applies it from its next run. */
1099
1099
  async function set_member_access({ name, project_access }) {
1100
1100
  const room_id = state.room.id;
1101
- state.free_error = ""; state.free_notice = "";
1102
- try {
1103
- await local_launch_request("room-member-access", { room_id, token: localStorage.getItem(`discuss-access:${room_id}`), name, project_access });
1104
- if (state.room?.id !== room_id) return;
1105
- state.free_notice = `${name} 的项目文件已改为${project_access === "write" ? "可写" : "只读"},下次处理请求起生效,原会话保留。`;
1106
- // The saved choices are cached per runtime revision, which this change leaves alone.
1107
- state.launch.room_models = null;
1108
- load_room_models();
1109
- } catch (error) { state.free_error = error.message; throw error; }
1101
+ await local_launch_request("room-member-access", { room_id, token: localStorage.getItem(`discuss-access:${room_id}`), name, project_access });
1102
+ if (state.room?.id !== room_id) return;
1103
+ // The saved choices are cached per runtime revision, which this change leaves alone.
1104
+ state.launch.room_models = null;
1105
+ await load_room_models();
1106
+ }
1107
+
1108
+ /** Switch an idle Codex member between the App and the CLI; its conversation stays. */
1109
+ async function set_member_adapter({ name, adapter }) {
1110
+ const room_id = state.room.id;
1111
+ await local_launch_request("room-member-adapter", { room_id, token: localStorage.getItem(`discuss-access:${room_id}`), name, adapter });
1112
+ if (state.room?.id !== room_id) return;
1113
+ state.launch.room_models = null;
1114
+ await load_room_models();
1110
1115
  }
1111
1116
 
1112
1117
  /** Owner changes use the website; only automatic members need the local service to reconnect. */
@@ -1702,7 +1707,7 @@ async function local_launch_request(action, payload) {
1702
1707
  method: payload === undefined ? "GET" : "POST", headers, credentials: "omit", redirect: "error",
1703
1708
  body: payload === undefined ? undefined : JSON.stringify(payload),
1704
1709
  ...(payload === undefined || ["room-models", "models", "api-check", "scheduler-check"].includes(action)
1705
- ? { signal: AbortSignal.timeout(["models", "api-check", "scheduler-check"].includes(action) ? MODEL_CATALOG_TIMEOUT_MS : LOCAL_CONNECTION_TIMEOUT_MS) } : {}) });
1710
+ ? { signal: AbortSignal.timeout(["room-models", "models", "api-check", "scheduler-check"].includes(action) ? MODEL_CATALOG_TIMEOUT_MS : LOCAL_CONNECTION_TIMEOUT_MS) } : {}) });
1706
1711
  } catch (error) {
1707
1712
  if (!local_connection) throw error;
1708
1713
  throw new Error("无法连接本机服务:请在这台电脑运行 codiscuss local open,并允许浏览器访问本机网络,再重试原请求");
@@ -1897,15 +1902,33 @@ async function load_room_models() {
1897
1902
  && (previous.loading || previous.participants)) return;
1898
1903
  const current = { room_id: room.id, revision, loading: true, participants: null };
1899
1904
  state.launch.room_models = current;
1905
+ const live = () => state.launch.room_models === current && state.room?.id === room.id;
1906
+ // agy is run to name its default model, which takes seconds; everything else is shown first and agy follows.
1900
1907
  try {
1901
- const result = await local_launch_request("room-models", { room_id: room.id });
1902
- if (state.launch.room_models !== current || state.room?.id !== room.id) return;
1903
- if (result.room_id === room.id) Object.assign(current, { participants: result.participants, registered: result.registered, scheduler: result.scheduler || null });
1904
- } catch { /* Unavailable or older bridges leave the model explicitly unknown. */ }
1905
- finally {
1908
+ const result = await local_launch_request("room-models", { room_id: room.id, quick: true });
1909
+ if (live() && result.room_id === room.id) Object.assign(current, { participants: result.participants, registered: result.registered, scheduler: result.scheduler || null });
1910
+ } catch (error) {
1911
+ // Unavailable or older bridges leave the model unknown; the failure is kept so the page can say so, and the next refresh retries.
1912
+ current.error = error.message || "读取失败";
1913
+ } finally {
1906
1914
  current.loading = false;
1907
- if (state.launch.room_models === current && state.room?.id === room.id) publish_view();
1915
+ if (live()) publish_view();
1908
1916
  }
1917
+ const pending = Object.entries(current.participants || {}).filter(([, profile]) => profile.defaults_pending).map(([name]) => name);
1918
+ if (!pending.length || !live()) return;
1919
+ try {
1920
+ const result = await local_launch_request("room-models", { room_id: room.id });
1921
+ if (live() && result.room_id === room.id) current.participants = result.participants;
1922
+ } catch {
1923
+ // A slow agy that fails to answer keeps its model unknown rather than guessed.
1924
+ for (const name of pending) current.participants[name] = { ...current.participants[name], defaults_pending: false, defaults_failed: true };
1925
+ } finally { if (live()) publish_view(); }
1926
+ }
1927
+
1928
+ /** Read this computer's saved choices again, as after a failed read. */
1929
+ function reload_room_models() {
1930
+ state.launch.room_models = null;
1931
+ return load_room_models();
1909
1932
  }
1910
1933
 
1911
1934
  /** Describe registered launch choices; an empty choice shows what the software's own settings select, or says the software decides. */
@@ -1916,6 +1939,9 @@ function participant_model(name, room, saved) {
1916
1939
  const profile = saved?.room_id === room.id ? saved.participants?.[name] : null;
1917
1940
  if (!profile) return "";
1918
1941
  if (["codex", "antigravity"].includes(profile.adapter)) return "模型与强度由 App 设置";
1942
+ // Only an agy member without a chosen model depends on the default that is read later.
1943
+ if (!profile.model && profile.defaults_pending) return "读取中…";
1944
+ if (!profile.model && profile.defaults_failed) return "";
1919
1945
  const model = profile.model || profile.default_model || "软件默认模型";
1920
1946
  // agy's default effort belongs to its default model, so a chosen model keeps its own default instead.
1921
1947
  const default_effort = profile.adapter === "antigravity_cli" && profile.model ? "" : profile.default_effort;
@@ -3505,7 +3531,7 @@ async function execute_view_action(name, value) {
3505
3531
  copy_online: () => copy_context(), copy_cli: () => copy_context("cli"), copy_background,
3506
3532
  choose_runtime, export_runtime, download_member_access, copy_member_access_text, copy_member_join, copy_member_launch: name => copy_member_join(name, true), pause_runtime, check_limits, pause_discussion, restart_discussion, retry_execution, conclude_discussion, start_room_discussion, end_room_discussion, reopen_discussion,
3507
3533
  save_launch_defaults, launch_current_room, resume_launch, discard_launch, retry_launch_connection, check_launch_connection: load_launch_settings,
3508
- load_room_configuration, save_room_configuration, interrupt_member, change_member, set_member_access, reorder_speakers, invite_member, set_proxy, copy_online_notice,
3534
+ load_room_configuration, save_room_configuration, interrupt_member, change_member, reorder_speakers, invite_member, set_proxy, copy_online_notice,
3509
3535
  prepare_brainstorm, return_conclusion, adopt_recommendation, rate_decision,
3510
3536
  busy: () => { throw new Error("上一个操作仍在处理中,请稍候;长时间无响应请刷新页面"); },
3511
3537
  copy_reading: () => copy_text(`${location.origin}/r/${state.room.id}`), copy: copy_text };
@@ -3536,7 +3562,7 @@ window.discuss_view = { snapshot: view_snapshot, write_field: write_view_field,
3536
3562
  admin: { register: register_admin, login: login_admin, logout: logout_admin,
3537
3563
  update_profile: update_admin_profile, avatar_from_file: admin_avatar_from_file, validate: validate_admin_form },
3538
3564
  request: request_json, identities: IDENTITIES, display_name, sources: SOURCE_LABELS, phases: PHASE_LABELS,
3539
- runtime_label, execution_label, limits_label, stop_reason_label, participant_model, participant_access, can_retry_execution,
3565
+ set_member_access, set_member_adapter, reload_room_models, runtime_label, execution_label, limits_label, stop_reason_label, participant_model, participant_access, can_retry_execution,
3540
3566
  turns: TURN_LABELS, turn_label, turn_guidance, progress_round, round_groups, limit_rounds, progress_speaker, brief_meta, max_message_length: MAX_MESSAGE_LENGTH, provenance: message_provenance, format_time };
3541
3567
 
3542
3568
  restore_theme();