ai_co_discuss 0.2.85 → 0.2.87

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
@@ -1105,6 +1105,15 @@ async function set_member_access({ name, project_access }) {
1105
1105
  await load_room_models();
1106
1106
  }
1107
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();
1115
+ }
1116
+
1108
1117
  /** Owner changes use the website; only automatic members need the local service to reconnect. */
1109
1118
  async function change_member({ member_id, name, action, role, latest_id }) {
1110
1119
  const room_id = state.room.id;
@@ -1698,7 +1707,7 @@ async function local_launch_request(action, payload) {
1698
1707
  method: payload === undefined ? "GET" : "POST", headers, credentials: "omit", redirect: "error",
1699
1708
  body: payload === undefined ? undefined : JSON.stringify(payload),
1700
1709
  ...(payload === undefined || ["room-models", "models", "api-check", "scheduler-check"].includes(action)
1701
- ? { 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) } : {}) });
1702
1711
  } catch (error) {
1703
1712
  if (!local_connection) throw error;
1704
1713
  throw new Error("无法连接本机服务:请在这台电脑运行 codiscuss local open,并允许浏览器访问本机网络,再重试原请求");
@@ -1893,15 +1902,33 @@ async function load_room_models() {
1893
1902
  && (previous.loading || previous.participants)) return;
1894
1903
  const current = { room_id: room.id, revision, loading: true, participants: null };
1895
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.
1896
1907
  try {
1897
- const result = await local_launch_request("room-models", { room_id: room.id });
1898
- if (state.launch.room_models !== current || state.room?.id !== room.id) return;
1899
- if (result.room_id === room.id) Object.assign(current, { participants: result.participants, registered: result.registered, scheduler: result.scheduler || null });
1900
- } catch { /* Unavailable or older bridges leave the model explicitly unknown. */ }
1901
- 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 {
1902
1914
  current.loading = false;
1903
- if (state.launch.room_models === current && state.room?.id === room.id) publish_view();
1915
+ if (live()) publish_view();
1904
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();
1905
1932
  }
1906
1933
 
1907
1934
  /** Describe registered launch choices; an empty choice shows what the software's own settings select, or says the software decides. */
@@ -1912,6 +1939,9 @@ function participant_model(name, room, saved) {
1912
1939
  const profile = saved?.room_id === room.id ? saved.participants?.[name] : null;
1913
1940
  if (!profile) return "";
1914
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 "";
1915
1945
  const model = profile.model || profile.default_model || "软件默认模型";
1916
1946
  // agy's default effort belongs to its default model, so a chosen model keeps its own default instead.
1917
1947
  const default_effort = profile.adapter === "antigravity_cli" && profile.model ? "" : profile.default_effort;
@@ -3532,7 +3562,7 @@ window.discuss_view = { snapshot: view_snapshot, write_field: write_view_field,
3532
3562
  admin: { register: register_admin, login: login_admin, logout: logout_admin,
3533
3563
  update_profile: update_admin_profile, avatar_from_file: admin_avatar_from_file, validate: validate_admin_form },
3534
3564
  request: request_json, identities: IDENTITIES, display_name, sources: SOURCE_LABELS, phases: PHASE_LABELS,
3535
- set_member_access, 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,
3536
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 };
3537
3567
 
3538
3568
  restore_theme();