@ycodium-ai/plugin-im 0.2.3034 → 0.2.3056

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/dist/index.js CHANGED
@@ -14549,20 +14549,20 @@ var require_axios = __commonJS({
14549
14549
  if (parts[0] !== "127") return false;
14550
14550
  return parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255);
14551
14551
  };
14552
- var parseIPv4Octet = (text3) => {
14553
- if (/^0[xX][0-9a-fA-F]+$/.test(text3)) {
14554
- const n = parseInt(text3.slice(2), 16);
14552
+ var parseIPv4Octet = (text4) => {
14553
+ if (/^0[xX][0-9a-fA-F]+$/.test(text4)) {
14554
+ const n = parseInt(text4.slice(2), 16);
14555
14555
  return Number.isFinite(n) ? n : null;
14556
14556
  }
14557
- if (text3.length > 1 && /^0[0-7]+$/.test(text3)) {
14558
- const n = parseInt(text3, 8);
14557
+ if (text4.length > 1 && /^0[0-7]+$/.test(text4)) {
14558
+ const n = parseInt(text4, 8);
14559
14559
  return Number.isFinite(n) ? n : null;
14560
14560
  }
14561
- if (text3.length > 1 && /^0[0-9]+$/.test(text3)) {
14561
+ if (text4.length > 1 && /^0[0-9]+$/.test(text4)) {
14562
14562
  return null;
14563
14563
  }
14564
- if (/^[0-9]+$/.test(text3)) {
14565
- const n = parseInt(text3, 10);
14564
+ if (/^[0-9]+$/.test(text4)) {
14565
+ const n = parseInt(text4, 10);
14566
14566
  return Number.isFinite(n) ? n : null;
14567
14567
  }
14568
14568
  return null;
@@ -23360,7 +23360,7 @@ var require_websocket = __commonJS({
23360
23360
  var http = __require("http");
23361
23361
  var net = __require("net");
23362
23362
  var tls = __require("tls");
23363
- var { randomBytes, createHash: createHash3 } = __require("crypto");
23363
+ var { randomBytes, createHash: createHash4 } = __require("crypto");
23364
23364
  var { Duplex, Readable } = __require("stream");
23365
23365
  var { URL: URL2 } = __require("url");
23366
23366
  var PerMessageDeflate = require_permessage_deflate();
@@ -24028,7 +24028,7 @@ var require_websocket = __commonJS({
24028
24028
  abortHandshake(websocket, socket, "Invalid Upgrade header");
24029
24029
  return;
24030
24030
  }
24031
- const digest = createHash3("sha1").update(key + GUID).digest("base64");
24031
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
24032
24032
  if (res.headers["sec-websocket-accept"] !== digest) {
24033
24033
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
24034
24034
  return;
@@ -24397,7 +24397,7 @@ var require_websocket_server = __commonJS({
24397
24397
  var EventEmitter = __require("events");
24398
24398
  var http = __require("http");
24399
24399
  var { Duplex } = __require("stream");
24400
- var { createHash: createHash3 } = __require("crypto");
24400
+ var { createHash: createHash4 } = __require("crypto");
24401
24401
  var extension = require_extension();
24402
24402
  var PerMessageDeflate = require_permessage_deflate();
24403
24403
  var subprotocol = require_subprotocol();
@@ -24704,7 +24704,7 @@ var require_websocket_server = __commonJS({
24704
24704
  );
24705
24705
  }
24706
24706
  if (this._state > RUNNING) return abortHandshake(socket, 503);
24707
- const digest = createHash3("sha1").update(key + GUID).digest("base64");
24707
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
24708
24708
  const headers = [
24709
24709
  "HTTP/1.1 101 Switching Protocols",
24710
24710
  "Upgrade: websocket",
@@ -122993,10 +122993,10 @@ var require_lib2 = __commonJS({
122993
122993
  }
122994
122994
  return prev + next;
122995
122995
  }
122996
- function splitWithCodeFences(text3, limit) {
122997
- if (text3.length <= limit)
122998
- return [text3];
122999
- const lines = text3.split("\n");
122996
+ function splitWithCodeFences(text4, limit) {
122997
+ if (text4.length <= limit)
122998
+ return [text4];
122999
+ const lines = text4.split("\n");
123000
123000
  const out = [];
123001
123001
  let buf = [];
123002
123002
  let bufLen = 0;
@@ -123041,10 +123041,10 @@ var require_lib2 = __commonJS({
123041
123041
  var ERROR_FOOTER = "\n\n\u2014 _(Generation interrupted)_";
123042
123042
  var DEFAULT_MAX_ELEMENT_CHARS = 3e4;
123043
123043
  var ELEMENT_ID = "stream_md";
123044
- function truncateSummary(text3, max = SUMMARY_MAX_CHARS) {
123045
- if (!text3)
123044
+ function truncateSummary(text4, max = SUMMARY_MAX_CHARS) {
123045
+ if (!text4)
123046
123046
  return "";
123047
- const cleaned = text3.replace(/\s+/g, " ").trim();
123047
+ const cleaned = text4.replace(/\s+/g, " ").trim();
123048
123048
  return cleaned.length <= max ? cleaned : cleaned.slice(0, max - 1) + "\u2026";
123049
123049
  }
123050
123050
  function buildStreamingCard(initialText) {
@@ -123755,21 +123755,21 @@ var require_lib2 = __commonJS({
123755
123755
  }
123756
123756
  return parts.length > 0 ? parts.join(" ") + " " : "";
123757
123757
  }
123758
- function optimizeMarkdownStyle(text3, cardVersion = 1) {
123758
+ function optimizeMarkdownStyle(text4, cardVersion = 1) {
123759
123759
  try {
123760
- return _optimize(text3, cardVersion);
123760
+ return _optimize(text4, cardVersion);
123761
123761
  } catch (_a) {
123762
- return text3;
123762
+ return text4;
123763
123763
  }
123764
123764
  }
123765
- function _optimize(text3, cardVersion) {
123765
+ function _optimize(text4, cardVersion) {
123766
123766
  const MARK = "___CB_";
123767
123767
  const codeBlocks = [];
123768
- let r = text3.replace(/(^|\n)(`{3,})([^\n]*)\n[\s\S]*?\n\2(?=\n|$)/g, (m, prefix = "") => {
123768
+ let r = text4.replace(/(^|\n)(`{3,})([^\n]*)\n[\s\S]*?\n\2(?=\n|$)/g, (m, prefix = "") => {
123769
123769
  const block2 = m.slice(String(prefix).length);
123770
123770
  return `${prefix}${MARK}${codeBlocks.push(block2) - 1}___`;
123771
123771
  });
123772
- const hasH1toH3 = /^#{1,3} /m.test(text3);
123772
+ const hasH1toH3 = /^#{1,3} /m.test(text4);
123773
123773
  if (hasH1toH3) {
123774
123774
  r = r.replace(/^#{2,6} (.+)$/gm, "##### $1");
123775
123775
  r = r.replace(/^# (.+)$/gm, "#### $1");
@@ -123805,11 +123805,11 @@ ${block2}
123805
123805
  function markdownToPost(md2, opts) {
123806
123806
  var _a, _b;
123807
123807
  const prefix = composeMentionsTextPrefix((_a = opts === null || opts === void 0 ? void 0 : opts.mentions) !== null && _a !== void 0 ? _a : []);
123808
- const text3 = optimizeMarkdownStyle(prefix + md2, 1);
123808
+ const text4 = optimizeMarkdownStyle(prefix + md2, 1);
123809
123809
  return {
123810
123810
  zh_cn: {
123811
123811
  title: (_b = opts === null || opts === void 0 ? void 0 : opts.title) !== null && _b !== void 0 ? _b : "",
123812
- content: [[{ tag: "md", text: text3 }]]
123812
+ content: [[{ tag: "md", text: text4 }]]
123813
123813
  }
123814
123814
  };
123815
123815
  }
@@ -124002,11 +124002,11 @@ ${block2}
124002
124002
  return this.makeResult(ids);
124003
124003
  });
124004
124004
  }
124005
- sendText(to, idType, text3, opts) {
124005
+ sendText(to, idType, text4, opts) {
124006
124006
  var _a;
124007
124007
  return __awaiter(this, void 0, void 0, function* () {
124008
124008
  const prefix = composeMentionsTextPrefix((_a = opts.mentions) !== null && _a !== void 0 ? _a : []);
124009
- const body = prefix + text3;
124009
+ const body = prefix + text4;
124010
124010
  const chunks = splitPlain(body, this.chunkLimit);
124011
124011
  const ids = [];
124012
124012
  for (let i = 0; i < chunks.length; i++) {
@@ -124328,12 +124328,12 @@ ${block2}
124328
124328
  };
124329
124329
  }
124330
124330
  };
124331
- function splitPlain(text3, limit) {
124332
- if (text3.length <= limit)
124333
- return [text3];
124331
+ function splitPlain(text4, limit) {
124332
+ if (text4.length <= limit)
124333
+ return [text4];
124334
124334
  const out = [];
124335
- for (let i = 0; i < text3.length; i += limit) {
124336
- out.push(text3.slice(i, i + limit));
124335
+ for (let i = 0; i < text4.length; i += limit) {
124336
+ out.push(text4.slice(i, i + limit));
124337
124337
  }
124338
124338
  return out;
124339
124339
  }
@@ -124854,10 +124854,10 @@ ${block2}
124854
124854
  return void 0;
124855
124855
  }
124856
124856
  }
124857
- function applyStyle(text3, style) {
124857
+ function applyStyle(text4, style) {
124858
124858
  if (!style || style.length === 0)
124859
- return text3;
124860
- let out = text3;
124859
+ return text4;
124860
+ let out = text4;
124861
124861
  if (style.includes("bold"))
124862
124862
  out = `**${out}**`;
124863
124863
  if (style.includes("italic"))
@@ -124921,8 +124921,8 @@ ${block2}
124921
124921
  const s = String(d.getUTCSeconds()).padStart(2, "0");
124922
124922
  return `${y}-${mo}-${day}T${h}:${mi}:${s}+08:00`;
124923
124923
  }
124924
- function indentLines(text3, indent) {
124925
- return text3.split("\n").map((line) => `${indent}${line}`).join("\n");
124924
+ function indentLines(text4, indent) {
124925
+ return text4.split("\n").map((line) => `${indent}${line}`).join("\n");
124926
124926
  }
124927
124927
  function escapeAttr(s) {
124928
124928
  return s.replace(/"/g, "&quot;");
@@ -125044,9 +125044,9 @@ ${formatCalendarInner(raw)}
125044
125044
  if (obj.text)
125045
125045
  visit(obj.text, out);
125046
125046
  if (typeof tag === "string" && tag === "button") {
125047
- const text3 = obj.text;
125048
- if (text3)
125049
- visit(text3, out);
125047
+ const text4 = obj.text;
125048
+ if (text4)
125049
+ visit(text4, out);
125050
125050
  }
125051
125051
  if (obj.label)
125052
125052
  visit(obj.label, out);
@@ -125800,13 +125800,13 @@ ${lines.join("\n")}
125800
125800
  * use this on a card would hit the same API and fail with a clearer
125801
125801
  * Feishu-side error.
125802
125802
  */
125803
- editMessage(messageId, text3) {
125803
+ editMessage(messageId, text4) {
125804
125804
  return __awaiter(this, void 0, void 0, function* () {
125805
125805
  yield this.rawClient.im.v1.message.update({
125806
125806
  path: { message_id: messageId },
125807
125807
  data: {
125808
125808
  msg_type: "text",
125809
- content: JSON.stringify({ text: text3 })
125809
+ content: JSON.stringify({ text: text4 })
125810
125810
  }
125811
125811
  });
125812
125812
  });
@@ -126236,6 +126236,18 @@ var foldAliased = (state, data) => {
126236
126236
  return { ...state, aliases: { ...state.aliases, [key]: chatId } };
126237
126237
  };
126238
126238
 
126239
+ // src/teamGoalOwners.ts
126240
+ var text = (value2) => typeof value2 === "string" && value2 !== "" ? value2 : null;
126241
+ var readTeamGoalStarted = (data) => {
126242
+ const chatKey = text(data["chatKey"]);
126243
+ const threadId = text(data["threadId"]);
126244
+ return chatKey === null || threadId === null ? null : { chatKey, threadId };
126245
+ };
126246
+ var recordOwner = (owners, goal) => ({
126247
+ ...owners,
126248
+ [goal.threadId]: { chatKey: goal.chatKey }
126249
+ });
126250
+
126239
126251
  // src/keepNewest.ts
126240
126252
  var keepNewest = (record2, limit) => {
126241
126253
  const entries = Object.entries(record2);
@@ -126275,7 +126287,7 @@ var chatOf = (state, chatKey) => ({
126275
126287
  ...state.chats[chatKey]
126276
126288
  });
126277
126289
  var chatsOnProject = (state, projectId) => Object.entries(state.chats).filter(([, record2]) => record2.projectId === projectId).map(([chatKey]) => chatKey);
126278
- var chatOfThread = (state, threadId) => Object.entries(state.chats).find(([, record2]) => record2.threadId === threadId)?.[0];
126290
+ var chatOfThread = (state, threadId) => Object.entries(state.chats).find(([, record2]) => record2.threadId === threadId)?.[0] ?? state.teamGoals?.[threadId]?.chatKey;
126279
126291
  var findApprovalByToken = (state, token) => {
126280
126292
  for (const approval of Object.values(state.approvals)) {
126281
126293
  const button = approval.options.find((option) => option.token === token);
@@ -126316,8 +126328,7 @@ var nonEmpty3 = (value2) => typeof value2 === "string" && value2 !== "" ? value2
126316
126328
  var readTarget = (value2) => {
126317
126329
  if (!isRecord(value2)) return null;
126318
126330
  if (value2["kind"] === "thread") return { kind: "thread" };
126319
- const teamId = nonEmpty3(value2["teamId"]);
126320
- return value2["kind"] === "team" && teamId !== null ? { kind: "team", teamId } : null;
126331
+ return value2["kind"] === "team" ? { kind: "team" } : null;
126321
126332
  };
126322
126333
  var readButtons = (value2) => {
126323
126334
  if (!Array.isArray(value2)) return null;
@@ -126449,6 +126460,12 @@ var foldImEvent = (state, name, data) => {
126449
126460
  )
126450
126461
  };
126451
126462
  }
126463
+ case "team-goal-started": {
126464
+ const goal = readTeamGoalStarted(data);
126465
+ if (goal === null) return state;
126466
+ const bound = withChat(state, goal.chatKey, { threadId: goal.threadId });
126467
+ return { ...bound, teamGoals: recordOwner(bound.teamGoals, goal) };
126468
+ }
126452
126469
  case "thread-attached": {
126453
126470
  const record2 = readAttached(data);
126454
126471
  if (record2 === null) return state;
@@ -127052,8 +127069,8 @@ var isAllowedSender = (bot, sender) => {
127052
127069
  };
127053
127070
 
127054
127071
  // src/numberedReply.ts
127055
- var optionIndexFrom = (text3, count) => {
127056
- const trimmed = text3.trim();
127072
+ var optionIndexFrom = (text4, count) => {
127073
+ const trimmed = text4.trim();
127057
127074
  if (!/^\d+$/.test(trimmed)) return null;
127058
127075
  const index = Number.parseInt(trimmed, 10);
127059
127076
  return Number.isInteger(index) && index >= 1 && index <= count ? index : null;
@@ -127071,10 +127088,10 @@ var DECISION_WORDS = /* @__PURE__ */ new Map([
127071
127088
  ["decline", "decline"],
127072
127089
  ["no", "decline"]
127073
127090
  ]);
127074
- var answerByNumber = (text3, options) => {
127075
- const index = optionIndexFrom(text3, options.length);
127091
+ var answerByNumber = (text4, options) => {
127092
+ const index = optionIndexFrom(text4, options.length);
127076
127093
  if (index !== null) return options[index - 1]?.token ?? null;
127077
- const said = text3.trim().toLowerCase();
127094
+ const said = text4.trim().toLowerCase();
127078
127095
  if (said.length === 0) return null;
127079
127096
  const byLabel = options.find((option) => option.label.trim().toLowerCase() === said);
127080
127097
  if (byLabel !== void 0) return byLabel.token;
@@ -127418,46 +127435,46 @@ var makeChatSetup = (core, deps) => {
127418
127435
  import { threadOrNull as threadOrNull2 } from "@ycodium-ai/plugin-api";
127419
127436
 
127420
127437
  // src/chatCommand.ts
127421
- var teamArgument = (text3, chinese) => {
127422
- const match = text3.match(/^\/team(?:\s+([\s\S]*))?$/i);
127438
+ var teamArgument = (text4, chinese) => {
127439
+ const match = text4.match(/^\/team(?:\s+([\s\S]*))?$/i);
127423
127440
  if (match) return (match[1] ?? "").trim();
127424
127441
  if (!chinese) return void 0;
127425
- const alias = text3.match(/^换团队(?:\s+([\s\S]*))?$/);
127442
+ const alias = text4.match(/^换团队(?:\s+([\s\S]*))?$/);
127426
127443
  return alias ? (alias[1] ?? "").trim() : void 0;
127427
127444
  };
127428
- var resumeArgument = (text3, chinese) => {
127429
- const match = text3.match(/^\/resume(?:\s+([\s\S]*))?$/i);
127445
+ var resumeArgument = (text4, chinese) => {
127446
+ const match = text4.match(/^\/resume(?:\s+([\s\S]*))?$/i);
127430
127447
  if (match) return (match[1] ?? "").trim();
127431
127448
  if (!chinese) return void 0;
127432
- const alias = text3.match(/^切换会话(?:\s+([\s\S]*))?$/);
127449
+ const alias = text4.match(/^切换会话(?:\s+([\s\S]*))?$/);
127433
127450
  return alias ? (alias[1] ?? "").trim() : void 0;
127434
127451
  };
127435
- var modelArgument = (text3, chinese) => {
127436
- const match = text3.match(/^\/model(?:\s+([\s\S]*))?$/i);
127452
+ var modelArgument = (text4, chinese) => {
127453
+ const match = text4.match(/^\/model(?:\s+([\s\S]*))?$/i);
127437
127454
  if (match) return (match[1] ?? "").trim();
127438
127455
  if (!chinese) return void 0;
127439
- const alias = text3.match(/^换模型(?:\s+([\s\S]*))?$/);
127456
+ const alias = text4.match(/^换模型(?:\s+([\s\S]*))?$/);
127440
127457
  return alias ? (alias[1] ?? "").trim() : void 0;
127441
127458
  };
127442
- var planArgument = (text3, chinese) => {
127443
- const match = text3.match(/^\/plan(?:\s+([\s\S]*))?$/i);
127459
+ var planArgument = (text4, chinese) => {
127460
+ const match = text4.match(/^\/plan(?:\s+([\s\S]*))?$/i);
127444
127461
  if (match) return (match[1] ?? "").trim().toLowerCase();
127445
127462
  if (!chinese) return void 0;
127446
- const alias = text3.match(/^计划模式(?:\s+([\s\S]*))?$/);
127463
+ const alias = text4.match(/^计划模式(?:\s+([\s\S]*))?$/);
127447
127464
  return alias ? (alias[1] ?? "").trim().toLowerCase() : void 0;
127448
127465
  };
127449
- var repoArgument = (text3, chinese) => {
127450
- const match = text3.match(/^\/repo(?:\s+([\s\S]*))?$/i);
127466
+ var repoArgument = (text4, chinese) => {
127467
+ const match = text4.match(/^\/repo(?:\s+([\s\S]*))?$/i);
127451
127468
  if (match) return (match[1] ?? "").trim();
127452
127469
  if (!chinese) return void 0;
127453
- const alias = text3.match(/^换项目(?:\s+([\s\S]*))?$/);
127470
+ const alias = text4.match(/^换项目(?:\s+([\s\S]*))?$/);
127454
127471
  return alias ? (alias[1] ?? "").trim() : void 0;
127455
127472
  };
127456
- var groupArgument = (text3, chinese) => {
127457
- const match = text3.match(/^\/group(?:\s+([\s\S]*))?$/i);
127473
+ var groupArgument = (text4, chinese) => {
127474
+ const match = text4.match(/^\/group(?:\s+([\s\S]*))?$/i);
127458
127475
  if (match) return (match[1] ?? "").trim();
127459
127476
  if (!chinese) return void 0;
127460
- const alias = text3.match(/^建群(?:\s+([\s\S]*))?$/);
127477
+ const alias = text4.match(/^建群(?:\s+([\s\S]*))?$/);
127461
127478
  return alias ? (alias[1] ?? "").trim() : void 0;
127462
127479
  };
127463
127480
  var planModeOf = (argument, chinese) => {
@@ -127466,7 +127483,7 @@ var planModeOf = (argument, chinese) => {
127466
127483
  if (argument === "off" || chinese && argument === "\u5173") return "off";
127467
127484
  return "invalid";
127468
127485
  };
127469
- var isThreadCommand = (text3, chinese) => /^\/thread$/i.test(text3.trim()) || chinese && text3.trim() === "\u6362\u5BF9\u8BDD";
127486
+ var isThreadCommand = (text4, chinese) => /^\/thread$/i.test(text4.trim()) || chinese && text4.trim() === "\u6362\u5BF9\u8BDD";
127470
127487
  var ZH_ALIASES = {
127471
127488
  \u505C: "stop",
127472
127489
  \u505C\u6B62: "stop",
@@ -127478,15 +127495,6 @@ var ZH_ALIASES = {
127478
127495
  \u9762\u677F: "panel",
127479
127496
  \u4F1A\u8BDD\u5217\u8868: "sessions"
127480
127497
  };
127481
- var resolveTeam = (query, teams) => {
127482
- const byId = teams.find((team) => team.teamId === query);
127483
- if (byId !== void 0) return byId;
127484
- const needle = query.toLowerCase();
127485
- const exact = teams.filter((team) => team.title.toLowerCase() === needle);
127486
- if (exact.length > 0) return exact.length === 1 ? exact[0] : void 0;
127487
- const prefixed = teams.filter((team) => team.title.toLowerCase().startsWith(needle));
127488
- return prefixed.length === 1 ? prefixed[0] : void 0;
127489
- };
127490
127498
  var parseChatCommand = (input) => {
127491
127499
  const trimmed = input.text.trim();
127492
127500
  if (/^\/stop$/i.test(trimmed)) return { kind: "stop" };
@@ -127510,10 +127518,7 @@ var parseChatCommand = (input) => {
127510
127518
  if (group !== void 0) return { kind: "group", name: group };
127511
127519
  const query = teamArgument(input.text, input.chinese);
127512
127520
  if (query !== void 0) {
127513
- if (input.teams.length === 0) return { kind: "noTeams" };
127514
- if (query.length === 0) return { kind: "showTargets" };
127515
- const team = resolveTeam(query, input.teams);
127516
- return team === void 0 ? { kind: "teamNotFound", query } : { kind: "selectTeam", team };
127521
+ return query === "" ? { kind: "selectTeam" } : { kind: "help" };
127517
127522
  }
127518
127523
  if (isThreadCommand(input.text, input.chinese)) return { kind: "selectThread" };
127519
127524
  if (/^\/[a-z][a-z0-9_-]*/i.test(trimmed)) return { kind: "help" };
@@ -127541,13 +127546,6 @@ var helpText = (t, options = {}) => [
127541
127546
  t("help.aliases"),
127542
127547
  ...options.panel === true ? ["", t("help.panel")] : []
127543
127548
  ].join("\n");
127544
- var describeTargets = (target2, teams, t) => {
127545
- const current = target2.kind === "thread" ? t("targets.currentThread") : t("targets.currentTeam", {
127546
- title: teams.find((team) => team.teamId === target2.teamId)?.title ?? target2.teamId
127547
- });
127548
- const list2 = teams.length === 0 ? t("targets.noTeams") : [t("targets.teamList"), ...teams.map((team) => `\xB7 ${team.title}`)].join("\n");
127549
- return [current, "", list2, "", t("targets.hint")].join("\n");
127550
- };
127551
127549
 
127552
127550
  // src/modelChoice.ts
127553
127551
  var MODEL_LIST_MAX = 30;
@@ -127608,10 +127606,7 @@ var NEEDS_PROJECT_COMMANDS = /* @__PURE__ */ new Set([
127608
127606
  "sessions",
127609
127607
  "resume",
127610
127608
  "selectTeam",
127611
- "selectThread",
127612
- "showTargets",
127613
- "teamNotFound",
127614
- "noTeams"
127609
+ "selectThread"
127615
127610
  ]);
127616
127611
  var makeCommands = (core, deps) => {
127617
127612
  const { host, t, commit, bindChat, deliver, hasPanel } = core;
@@ -127621,10 +127616,9 @@ var makeCommands = (core, deps) => {
127621
127616
  const { handleModel, handlePlan } = deps.modelPlan;
127622
127617
  const { openPanel } = deps;
127623
127618
  const targetOf = (binding) => chatOf(core.state, chatKeyOf(binding)).target;
127624
- const handleCommand = async (binding, text3, teams, senderId = null) => {
127619
+ const handleCommand = async (binding, text4, senderId = null) => {
127625
127620
  const command = parseChatCommand({
127626
- text: text3,
127627
- teams,
127621
+ text: text4,
127628
127622
  // 中文别名只在回话语言是中文时认,免得英文用户打一个「停」就被当成命令。
127629
127623
  chinese: t.language === "zh-CN"
127630
127624
  });
@@ -127649,33 +127643,20 @@ var makeCommands = (core, deps) => {
127649
127643
  await handleGroup(binding, command.name, senderId);
127650
127644
  return true;
127651
127645
  case "selectTeam":
127652
- commit("chat-updated", {
127653
- chatKey,
127654
- target: { kind: "team", teamId: command.team.teamId },
127655
- threadId: null
127656
- });
127657
- await deliver(binding, t("command.teamSelected", { title: command.team.title }));
127646
+ if (!await deps.teams.hasRosterFor(binding)) return true;
127647
+ if (targetOf(binding).kind !== "team") {
127648
+ commit("chat-updated", {
127649
+ chatKey,
127650
+ target: { kind: "team" },
127651
+ threadId: null
127652
+ });
127653
+ }
127654
+ await deliver(binding, t("command.teamSelected"));
127658
127655
  return true;
127659
127656
  case "selectThread":
127660
127657
  commit("chat-updated", { chatKey, target: { kind: "thread" }, threadId: null });
127661
127658
  await deliver(binding, t("command.threadSelected"));
127662
127659
  return true;
127663
- case "showTargets":
127664
- await deliver(binding, describeTargets(targetOf(binding), teams, t));
127665
- return true;
127666
- case "teamNotFound":
127667
- await deliver(
127668
- binding,
127669
- [
127670
- t("command.teamNotFound", { query: command.query }),
127671
- "",
127672
- describeTargets(targetOf(binding), teams, t)
127673
- ].join("\n")
127674
- );
127675
- return true;
127676
- case "noTeams":
127677
- await deliver(binding, t("command.noTeams"));
127678
- return true;
127679
127660
  case "help":
127680
127661
  await deliver(binding, helpText(t, { panel: hasPanel(binding) }));
127681
127662
  return true;
@@ -127711,9 +127692,7 @@ var makeCommands = (core, deps) => {
127711
127692
  case "status": {
127712
127693
  const threadId = chatOf(core.state, chatKey).threadId ?? void 0;
127713
127694
  const routed = targetOf(binding);
127714
- const where = routed.kind === "team" ? t("status.routedTeam", {
127715
- title: teams.find((team) => team.teamId === routed.teamId)?.title ?? routed.teamId
127716
- }) : t("status.routedThread");
127695
+ const where = routed.kind === "team" ? t("status.routedTeam") : t("status.routedThread");
127717
127696
  const planLine = chatOf(core.state, chatKey).plan ? [t("status.planOn")] : [];
127718
127697
  const projectLine2 = [
127719
127698
  binding.projectId === "" ? t("status.noProject") : t("status.project", {
@@ -127998,11 +127977,11 @@ var parseSendBody = (raw) => {
127998
127977
  const record2 = parsed;
127999
127978
  const botId = record2["botId"];
128000
127979
  const targetId = record2["targetId"];
128001
- const text3 = record2["text"];
127980
+ const text4 = record2["text"];
128002
127981
  const format2 = record2["format"];
128003
127982
  if (typeof botId !== "string" || botId.trim() === "") return "bad-request";
128004
127983
  if (typeof targetId !== "string" || targetId.trim() === "") return "bad-request";
128005
- if (typeof text3 !== "string" || text3.trim() === "") return "bad-request";
127984
+ if (typeof text4 !== "string" || text4.trim() === "") return "bad-request";
128006
127985
  if (format2 !== void 0 && format2 !== "plain" && format2 !== "markdown") return "bad-request";
128007
127986
  for (const key of Object.keys(record2)) {
128008
127987
  if (key !== "botId" && key !== "targetId" && key !== "text" && key !== "format") {
@@ -128012,7 +127991,7 @@ var parseSendBody = (raw) => {
128012
127991
  return {
128013
127992
  botId: botId.trim(),
128014
127993
  targetId: targetId.trim(),
128015
- text: text3,
127994
+ text: text4,
128016
127995
  format: format2 === "markdown" ? "markdown" : format2 === "plain" ? "plain" : void 0
128017
127996
  };
128018
127997
  };
@@ -128196,11 +128175,11 @@ var makeImCore = (input) => {
128196
128175
  }
128197
128176
  }
128198
128177
  };
128199
- const deliver = async (binding, text3, attachments = []) => {
128178
+ const deliver = async (binding, text4, attachments = []) => {
128200
128179
  await postImages(binding, attachments);
128201
- if (text3.trim() === "") return;
128180
+ if (text4.trim() === "") return;
128202
128181
  try {
128203
- await adapterFor(binding.platform)?.sendText(binding, text3);
128182
+ await adapterFor(binding.platform)?.sendText(binding, text4);
128204
128183
  } catch (error) {
128205
128184
  host.log.warn("chat could not deliver", { error: describeError(error) });
128206
128185
  }
@@ -128601,7 +128580,7 @@ var makeInbound = (core, deps) => {
128601
128580
  const { answerByToken } = deps.approvals;
128602
128581
  const { handlePanelClick } = deps.panelWiring;
128603
128582
  const { startTurn, receiveAttachmentsOnly, hasWaitingAttachments } = deps.turns;
128604
- const { fetchTeams, startTeamRun } = deps.teams;
128583
+ const { startTeamGoal } = deps.teams;
128605
128584
  const { markWorking } = deps.acknowledgements;
128606
128585
  const archivedReplyCooldown = makeCooldown(ARCHIVED_REPLY_COOLDOWN_MS, () => Date.now());
128607
128586
  const unsupportedReplyCooldown = makeCooldown(UNSUPPORTED_REPLY_COOLDOWN_MS, () => Date.now());
@@ -128710,8 +128689,7 @@ var makeInbound = (core, deps) => {
128710
128689
  reply: anchorOfMessage(adapterFor(current.platform), message)
128711
128690
  };
128712
128691
  const chatKey = chatKeyOf(target2);
128713
- const teams = await fetchTeams(target2);
128714
- if (await handleCommand(target2, message.text, teams ?? [], message.senderId)) return;
128692
+ if (await handleCommand(target2, message.text, message.senderId)) return;
128715
128693
  if (target2.projectId === "") {
128716
128694
  const asked = message.text.trim();
128717
128695
  if (/^[1-9]\d{0,2}$/u.test(asked) && listedProjectsByChat.has(chatKey)) {
@@ -128744,20 +128722,11 @@ var makeInbound = (core, deps) => {
128744
128722
  const routed = targetOf(target2);
128745
128723
  const attachmentsOnly = message.text.trim() === "" && message.resources.length > 0;
128746
128724
  if (routed.kind === "team") {
128747
- if (teams !== null && !teams.some((team) => team.teamId === routed.teamId)) {
128748
- commit("chat-updated", {
128749
- chatKey,
128750
- target: { kind: "thread" },
128751
- threadId: null
128752
- });
128753
- await deliver(target2, t("reply.teamGone"));
128754
- } else {
128755
- if (message.resources.length > 0) await deliver(target2, t("reply.attachmentsNoTeam"));
128756
- if (attachmentsOnly) return;
128757
- await startTeamRun(target2, routed.teamId, message.text);
128758
- await markWorking(target2, chatKey, message.messageId);
128759
- return;
128760
- }
128725
+ if (message.resources.length > 0) await deliver(target2, t("reply.attachmentsNoTeam"));
128726
+ if (attachmentsOnly) return;
128727
+ const leadThreadId = await startTeamGoal(target2, message);
128728
+ if (leadThreadId !== null) await markWorking(target2, leadThreadId, message.messageId);
128729
+ return;
128761
128730
  }
128762
128731
  if (attachmentsOnly) {
128763
128732
  await receiveAttachmentsOnly(target2, message);
@@ -128806,8 +128775,8 @@ var optionDescriptionOf = (item, option, t) => {
128806
128775
  };
128807
128776
  var QUESTION_TEXT_MAX_CHARS = 1500;
128808
128777
  var ANSWER_ECHO_MAX_CHARS = 200;
128809
- var clip = (text3, limit) => {
128810
- const chars = Array.from(text3.trim());
128778
+ var clip = (text4, limit) => {
128779
+ const chars = Array.from(text4.trim());
128811
128780
  return chars.length <= limit ? chars.join("") : `${chars.slice(0, limit).join("")}\u2026`;
128812
128781
  };
128813
128782
  var titleOf = (item, index, total, t) => {
@@ -128863,8 +128832,8 @@ var questionPlainText = (item, index, total, t) => [
128863
128832
  item.multiSelect ? t("question.replyMany") : t("question.replyOne"),
128864
128833
  ...item.allowFreeform ? [t("question.freeformHint")] : []
128865
128834
  ].join("\n");
128866
- var parseNumberedReply = (item, text3, t) => {
128867
- const trimmed = text3.trim();
128835
+ var parseNumberedReply = (item, text4, t) => {
128836
+ const trimmed = text4.trim();
128868
128837
  const pattern = item.multiSelect ? /^\d+(?:[\s,,、]+\d+)*$/ : /^\d+$/;
128869
128838
  if (!pattern.test(trimmed)) return null;
128870
128839
  const numbers = [...new Set(trimmed.split(/[\s,,、]+/).map(Number))];
@@ -129015,13 +128984,11 @@ var makeQuestionFlow = (host) => {
129015
128984
  return true;
129016
128985
  }
129017
128986
  try {
129018
- await host.dispatch({
129019
- type: "thread.user-input.respond",
129020
- commandId: host.newId(),
128987
+ await host.respondToUserInput({
128988
+ requestId: host.newId(),
129021
128989
  threadId: after.threadId,
129022
- requestId,
129023
- answers: Object.fromEntries(after.items.map((entry) => [entry.id, entry.answer])),
129024
- createdAt: host.now()
128990
+ userInputRequestId: requestId,
128991
+ answers: Object.fromEntries(after.items.map((entry) => [entry.id, entry.answer]))
129025
128992
  });
129026
128993
  } catch (error) {
129027
128994
  host.warn("chat could not hand the answer to the agent", error);
@@ -129057,9 +129024,9 @@ var makeQuestionFlow = (host) => {
129057
129024
  );
129058
129025
  return handledWith(null);
129059
129026
  };
129060
- const answerByText = async (chatKey, threadId, text3) => {
129027
+ const answerByText = async (chatKey, threadId, text4) => {
129061
129028
  const record2 = openQuestionOf(host.state(), chatKey, threadId);
129062
- const trimmed = text3.trim();
129029
+ const trimmed = text4.trim();
129063
129030
  if (record2 === void 0 || trimmed === "") return false;
129064
129031
  const unanswered = record2.items.filter(isUnanswered);
129065
129032
  const first = unanswered[0];
@@ -129187,7 +129154,7 @@ var makeQueueFlow = (host, deps) => {
129187
129154
  queuePaused: execution.queuePaused,
129188
129155
  intent: execution.intents.find((intent) => intent.intentId === intentId)
129189
129156
  });
129190
- const noteQueued = async (chatKey, threadId, messageId, text3, reply) => {
129157
+ const noteQueued = async (chatKey, threadId, messageId, text4, reply) => {
129191
129158
  const target2 = host.target(chatKey);
129192
129159
  if (target2 === void 0) return;
129193
129160
  let execution;
@@ -129213,7 +129180,7 @@ var makeQueueFlow = (host, deps) => {
129213
129180
  chatKey,
129214
129181
  threadId,
129215
129182
  intentId,
129216
- text: text3,
129183
+ text: text4,
129217
129184
  steerToken: host.newToken(),
129218
129185
  withdrawToken: host.newToken(),
129219
129186
  resumeToken: host.newToken()
@@ -129406,10 +129373,11 @@ var makeInteractions = (core, deps) => {
129406
129373
  });
129407
129374
  return false;
129408
129375
  },
129376
+ respondToUserInput: (input) => host.threads.userInput.respond(input),
129409
129377
  dispatch: (command) => host.commands.dispatch(command),
129410
- say: async (chatKey, text3) => {
129378
+ say: async (chatKey, text4) => {
129411
129379
  const binding = bindingForChatKey(chatKey);
129412
- if (binding !== void 0) await deliver(binding, text3);
129380
+ if (binding !== void 0) await deliver(binding, text4);
129413
129381
  },
129414
129382
  newToken: () => crypto.randomUUID().slice(0, 8),
129415
129383
  newId: () => crypto.randomUUID(),
@@ -129710,7 +129678,7 @@ var makeSettingsUpdater = (settings) => {
129710
129678
  var OPEN_ID_PREFIX = "ou_";
129711
129679
  var LARK_PLATFORM = "lark";
129712
129680
  var asRecord = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? { ...value2 } : {};
129713
- var text = (row, key) => {
129681
+ var text2 = (row, key) => {
129714
129682
  const value2 = row[key];
129715
129683
  return typeof value2 === "string" ? value2.trim() : "";
129716
129684
  };
@@ -129728,16 +129696,16 @@ var upsertLarkBot = (current, result) => {
129728
129696
  const sender = senderIdOf(result.creatorId);
129729
129697
  const existingId = Object.keys(table2).find((rowId2) => {
129730
129698
  const row2 = asRecord(table2[rowId2]);
129731
- const platform = text(row2, "platform") || DEFAULT_PLATFORM;
129732
- return platform === LARK_PLATFORM && text(row2, "larkAppId") === result.appId;
129699
+ const platform = text2(row2, "platform") || DEFAULT_PLATFORM;
129700
+ return platform === LARK_PLATFORM && text2(row2, "larkAppId") === result.appId;
129733
129701
  });
129734
129702
  const rowId = existingId ?? freeRowId(table2);
129735
129703
  const base2 = existingId === void 0 ? {} : asRecord(table2[existingId]);
129736
- const keptList = text(base2, "allowedSenders");
129704
+ const keptList = text2(base2, "allowedSenders");
129737
129705
  const allowedSenders = keptList !== "" ? keptList : sender ?? "";
129738
129706
  const row = {
129739
129707
  ...base2,
129740
- displayName: text(base2, "displayName") || result.appName,
129708
+ displayName: text2(base2, "displayName") || result.appName,
129741
129709
  platform: LARK_PLATFORM,
129742
129710
  larkAppId: result.appId,
129743
129711
  larkAppSecret: result.appSecret,
@@ -130212,10 +130180,10 @@ var openConsole = async (deps, jar) => {
130212
130180
  ...body === void 0 ? {} : { body },
130213
130181
  signal
130214
130182
  });
130215
- const text3 = await response.text();
130183
+ const text4 = await response.text();
130216
130184
  let data = null;
130217
130185
  try {
130218
- data = JSON.parse(text3);
130186
+ data = JSON.parse(text4);
130219
130187
  } catch {
130220
130188
  data = null;
130221
130189
  }
@@ -130439,8 +130407,8 @@ var TOKEN_LIKE = /[A-Za-z0-9_=-]{24,}/g;
130439
130407
  var MIN_SECRET_LENGTH = 6;
130440
130408
  var makeRedactor = () => {
130441
130409
  const secrets = /* @__PURE__ */ new Set();
130442
- const redact = (text3) => {
130443
- let out = text3;
130410
+ const redact = (text4) => {
130411
+ let out = text4;
130444
130412
  for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {
130445
130413
  out = out.split(secret).join(MASK);
130446
130414
  }
@@ -130451,7 +130419,7 @@ var makeRedactor = () => {
130451
130419
  if (typeof secret === "string" && secret.length >= MIN_SECRET_LENGTH) secrets.add(secret);
130452
130420
  },
130453
130421
  redact,
130454
- detail: (text3) => redact(text3).slice(0, DETAIL_MAX_CHARS)
130422
+ detail: (text4) => redact(text4).slice(0, DETAIL_MAX_CHARS)
130455
130423
  };
130456
130424
  };
130457
130425
 
@@ -131279,10 +131247,10 @@ var registerLarkSetup = (ctx, options = {}) => {
131279
131247
  };
131280
131248
 
131281
131249
  // src/splitMessage.ts
131282
- var splitMessage = (text3, limit) => {
131283
- if (text3.length <= limit) return [text3];
131250
+ var splitMessage = (text4, limit) => {
131251
+ if (text4.length <= limit) return [text4];
131284
131252
  const chunks = [];
131285
- let rest = text3;
131253
+ let rest = text4;
131286
131254
  while (rest.length > limit) {
131287
131255
  const window2 = rest.slice(0, limit);
131288
131256
  const paragraph2 = window2.lastIndexOf("\n\n");
@@ -131500,7 +131468,7 @@ var createChat = async (input) => {
131500
131468
  }
131501
131469
  return chatId;
131502
131470
  };
131503
- var splitForLark = (text3) => splitMessage(text3, LARK_TEXT_MAX_CHARS);
131471
+ var splitForLark = (text4) => splitMessage(text4, LARK_TEXT_MAX_CHARS);
131504
131472
 
131505
131473
  // src/larkCardStream.ts
131506
131474
  var LARK_CARD_THROTTLE_MS = 400;
@@ -132542,10 +132510,10 @@ var REBuilder = class {
132542
132510
  }
132543
132511
  };
132544
132512
  var web_schema = {
132545
- validate: (text3, pos, self2) => {
132513
+ validate: (text4, pos, self2) => {
132546
132514
  const re = self2.re.get_http_validator();
132547
132515
  re.lastIndex = pos;
132548
- const m = re.exec(text3);
132516
+ const m = re.exec(text4);
132549
132517
  return m ? m[0].length : 0;
132550
132518
  },
132551
132519
  normalize: (match, self2) => self2.normalize(match)
@@ -132555,13 +132523,13 @@ var defaultSchemas = {
132555
132523
  "https:": web_schema,
132556
132524
  "ftp:": web_schema,
132557
132525
  "//": {
132558
- validate: function(text3, pos, self2) {
132526
+ validate: function(text4, pos, self2) {
132559
132527
  const re = self2.re.get_relative_proto_validator();
132560
132528
  re.lastIndex = pos;
132561
- const m = re.exec(text3);
132529
+ const m = re.exec(text4);
132562
132530
  if (m) {
132563
- if (pos >= 3 && text3[pos - 3] === ":") return 0;
132564
- if (pos >= 3 && text3[pos - 3] === "/") return 0;
132531
+ if (pos >= 3 && text4[pos - 3] === ":") return 0;
132532
+ if (pos >= 3 && text4[pos - 3] === "/") return 0;
132565
132533
  return m[0].length;
132566
132534
  }
132567
132535
  return 0;
@@ -132569,10 +132537,10 @@ var defaultSchemas = {
132569
132537
  normalize: (match, self2) => self2.normalize(match)
132570
132538
  },
132571
132539
  "mailto:": {
132572
- validate: function(text3, pos, self2) {
132540
+ validate: function(text4, pos, self2) {
132573
132541
  const re = self2.re.get_mailto_validator();
132574
132542
  re.lastIndex = pos;
132575
- const m = re.exec(text3);
132543
+ const m = re.exec(text4);
132576
132544
  return m ? m[0].length : 0;
132577
132545
  },
132578
132546
  normalize: (match, self2) => self2.normalize(match)
@@ -132611,8 +132579,8 @@ var Match = class {
132611
132579
  text;
132612
132580
  /** Normalized URL of matched string. */
132613
132581
  url;
132614
- constructor(text3, schema, index, lastIndex) {
132615
- const raw = text3.slice(index, lastIndex);
132582
+ constructor(text4, schema, index, lastIndex) {
132583
+ const raw = text4.slice(index, lastIndex);
132616
132584
  this.schema = schema.toLowerCase();
132617
132585
  this.index = index;
132618
132586
  this.lastIndex = lastIndex;
@@ -132718,24 +132686,24 @@ var LinkifyIt = class {
132718
132686
  *
132719
132687
  * @param text Text to scan.
132720
132688
  */
132721
- test(text3) {
132722
- if (!text3.length) return false;
132689
+ test(text4) {
132690
+ if (!text4.length) return false;
132723
132691
  let m, re;
132724
132692
  re = this.re.get_schema_search();
132725
132693
  re.lastIndex = 0;
132726
- while ((m = re.exec(text3)) !== null) if (this.testSchemaAt(text3, m[2], re.lastIndex)) return true;
132694
+ while ((m = re.exec(text4)) !== null) if (this.testSchemaAt(text4, m[2], re.lastIndex)) return true;
132727
132695
  if (this.__opts__.fuzzyLink && this.__schemas__["http:"]) {
132728
132696
  re = this.re.get_fuzzy_link_search();
132729
132697
  re.lastIndex = 0;
132730
- if (re.exec(text3) !== null) return true;
132698
+ if (re.exec(text4) !== null) return true;
132731
132699
  }
132732
132700
  if (this.__opts__.fuzzyEmail && this.__schemas__["mailto:"]) {
132733
- if (text3.indexOf("@") >= 0) {
132701
+ if (text4.indexOf("@") >= 0) {
132734
132702
  const mailHostRe = this.re.get_fuzzy_mail_host_search();
132735
132703
  const mailNameRe = this.re.get_mail_name_validator();
132736
132704
  mailHostRe.lastIndex = 0;
132737
- while ((m = mailHostRe.exec(text3)) !== null) {
132738
- const name = text3.slice(Math.max(0, m.index - 65), m.index);
132705
+ while ((m = mailHostRe.exec(text4)) !== null) {
132706
+ const name = text4.slice(Math.max(0, m.index - 65), m.index);
132739
132707
  if (mailNameRe.test(name)) return true;
132740
132708
  }
132741
132709
  }
@@ -132750,9 +132718,9 @@ var LinkifyIt = class {
132750
132718
  * @param schema Rule (schema) name.
132751
132719
  * @param pos Text offset to check from.
132752
132720
  */
132753
- testSchemaAt(text3, schema, pos) {
132721
+ testSchemaAt(text4, schema, pos) {
132754
132722
  if (!this.__schemas__[schema.toLowerCase()]) return 0;
132755
- return this.__schemas__[schema.toLowerCase()].validate(text3.slice(0, pos + this.__opts__.maxLength), pos, this);
132723
+ return this.__schemas__[schema.toLowerCase()].validate(text4.slice(0, pos + this.__opts__.maxLength), pos, this);
132756
132724
  }
132757
132725
  /**
132758
132726
  * Returns array of found link descriptions or `null` on fail. We strongly
@@ -132760,7 +132728,7 @@ var LinkifyIt = class {
132760
132728
  *
132761
132729
  * @param text Text to scan.
132762
132730
  */
132763
- match(text3) {
132731
+ match(text4) {
132764
132732
  const result = [];
132765
132733
  const schemaRe = this.re.get_schema_search();
132766
132734
  let fuzzyLinkRe;
@@ -132773,7 +132741,7 @@ var LinkifyIt = class {
132773
132741
  let fuzzyLinkDone = false;
132774
132742
  let fuzzyEmailDone = false;
132775
132743
  let pos = 0;
132776
- if (!text3.length) return null;
132744
+ if (!text4.length) return null;
132777
132745
  schemaRe.lastIndex = 0;
132778
132746
  if (this.__opts__.fuzzyLink && this.__schemas__["http:"]) {
132779
132747
  fuzzyLinkRe = this.re.get_fuzzy_link_search();
@@ -132789,13 +132757,13 @@ var LinkifyIt = class {
132789
132757
  if (mailHostRe && mailNameRe && !fuzzyEmailDone && (!fuzzyEmailCandidate || fuzzyEmailCandidate.index < pos)) {
132790
132758
  if (mailHostRe.lastIndex < scanFrom) mailHostRe.lastIndex = scanFrom;
132791
132759
  for (; ; ) {
132792
- const m = mailHostRe.exec(text3);
132760
+ const m = mailHostRe.exec(text4);
132793
132761
  if (!m) {
132794
132762
  fuzzyEmailDone = true;
132795
132763
  fuzzyEmailCandidate = void 0;
132796
132764
  break;
132797
132765
  }
132798
- const name = mailNameRe.exec(text3.slice(Math.max(0, m.index - 65), m.index));
132766
+ const name = mailNameRe.exec(text4.slice(Math.max(0, m.index - 65), m.index));
132799
132767
  if (!name) continue;
132800
132768
  fuzzyEmailCandidate = {
132801
132769
  schema: "mailto:",
@@ -132809,7 +132777,7 @@ var LinkifyIt = class {
132809
132777
  if (fuzzyLinkRe && !fuzzyLinkDone && (!fuzzyLinkCandidate || fuzzyLinkCandidate.index < pos)) {
132810
132778
  if (fuzzyLinkRe.lastIndex < scanFrom) fuzzyLinkRe.lastIndex = scanFrom;
132811
132779
  for (; ; ) {
132812
- const m = fuzzyLinkRe.exec(text3);
132780
+ const m = fuzzyLinkRe.exec(text4);
132813
132781
  if (!m) {
132814
132782
  fuzzyLinkDone = true;
132815
132783
  fuzzyLinkCandidate = void 0;
@@ -132830,7 +132798,7 @@ var LinkifyIt = class {
132830
132798
  if (!schemaDone) for (; ; ) {
132831
132799
  if (!schemaPrefix) {
132832
132800
  if (schemaRe.lastIndex < scanFrom) schemaRe.lastIndex = scanFrom;
132833
- const m = schemaRe.exec(text3);
132801
+ const m = schemaRe.exec(text4);
132834
132802
  if (!m) {
132835
132803
  schemaDone = true;
132836
132804
  break;
@@ -132848,7 +132816,7 @@ var LinkifyIt = class {
132848
132816
  if (fuzzyCandidate && schemaPrefix.index > fuzzyCandidate.index) break;
132849
132817
  const prefix = schemaPrefix;
132850
132818
  schemaPrefix = void 0;
132851
- const len = this.testSchemaAt(text3, prefix.schema, prefix.lastIndex);
132819
+ const len = this.testSchemaAt(text4, prefix.schema, prefix.lastIndex);
132852
132820
  if (len) {
132853
132821
  schemaCandidate = {
132854
132822
  schema: prefix.schema,
@@ -132864,7 +132832,7 @@ var LinkifyIt = class {
132864
132832
  if (!candidate) break;
132865
132833
  if (candidate === fuzzyEmailCandidate) fuzzyEmailCandidate = void 0;
132866
132834
  else if (candidate === fuzzyLinkCandidate) fuzzyLinkCandidate = void 0;
132867
- const match = new Match(text3, candidate.schema, candidate.index, candidate.lastIndex);
132835
+ const match = new Match(text4, candidate.schema, candidate.index, candidate.lastIndex);
132868
132836
  if (match.schema) this.__schemas__[match.schema].normalize(match, this);
132869
132837
  else this.normalize(match);
132870
132838
  result.push(match);
@@ -132879,13 +132847,13 @@ var LinkifyIt = class {
132879
132847
  *
132880
132848
  * @param text Text to scan.
132881
132849
  */
132882
- matchAtStart(text3) {
132883
- if (!text3.length) return null;
132884
- const m = this.re.get_schema_at_start().exec(text3);
132850
+ matchAtStart(text4) {
132851
+ if (!text4.length) return null;
132852
+ const m = this.re.get_schema_at_start().exec(text4);
132885
132853
  if (!m) return null;
132886
- const len = this.testSchemaAt(text3, m[2], m[0].length);
132854
+ const len = this.testSchemaAt(text4, m[2], m[0].length);
132887
132855
  if (!len) return null;
132888
- const match = new Match(text3, m[2], m.index + m[1].length, m.index + m[0].length + len);
132856
+ const match = new Match(text4, m[2], m.index + m[1].length, m.index + m[0].length + len);
132889
132857
  this.__schemas__[match.schema].normalize(match, this);
132890
132858
  return match;
132891
132859
  }
@@ -133865,8 +133833,8 @@ function linkify$1(state) {
133865
133833
  }
133866
133834
  if (htmlLinkLevel > 0) continue;
133867
133835
  if (currentToken.type === "text" && state.md.linkify.test(currentToken.content)) {
133868
- const text3 = currentToken.content;
133869
- let links = state.md.linkify.match(text3);
133836
+ const text4 = currentToken.content;
133837
+ let links = state.md.linkify.match(text4);
133870
133838
  const nodes = [];
133871
133839
  let level = currentToken.level;
133872
133840
  let lastPos = 0;
@@ -133882,7 +133850,7 @@ function linkify$1(state) {
133882
133850
  const pos = links[ln].index;
133883
133851
  if (pos > lastPos) {
133884
133852
  const token = new state.Token("text", "", 0);
133885
- token.content = text3.slice(lastPos, pos);
133853
+ token.content = text4.slice(lastPos, pos);
133886
133854
  token.level = level;
133887
133855
  nodes.push(token);
133888
133856
  }
@@ -133903,9 +133871,9 @@ function linkify$1(state) {
133903
133871
  nodes.push(token_c);
133904
133872
  lastPos = links[ln].lastIndex;
133905
133873
  }
133906
- if (lastPos < text3.length) {
133874
+ if (lastPos < text4.length) {
133907
133875
  const token = new state.Token("text", "", 0);
133908
- token.content = text3.slice(lastPos);
133876
+ token.content = text4.slice(lastPos);
133909
133877
  token.level = level;
133910
133878
  nodes.push(token);
133911
133879
  }
@@ -134016,19 +133984,19 @@ function process_inlines(tokens, state) {
134016
133984
  for (j = stack.length - 1; j >= 0; j--) if (stack[j].level <= thisLevel) break;
134017
133985
  truncateStack(stack, heads, j + 1);
134018
133986
  if (token.type !== "text") continue;
134019
- const text3 = token.content;
133987
+ const text4 = token.content;
134020
133988
  let pos = 0;
134021
- const max = text3.length;
133989
+ const max = text4.length;
134022
133990
  OUTER: while (pos < max) {
134023
133991
  QUOTE_RE.lastIndex = pos;
134024
- const t = QUOTE_RE.exec(text3);
133992
+ const t = QUOTE_RE.exec(text4);
134025
133993
  if (!t) break;
134026
133994
  let canOpen = true;
134027
133995
  let canClose = true;
134028
133996
  pos = t.index + 1;
134029
133997
  const isSingle = t[0] === "'";
134030
133998
  let lastChar = 32;
134031
- if (t.index - 1 >= 0) lastChar = text3.charCodeAt(t.index - 1);
133999
+ if (t.index - 1 >= 0) lastChar = text4.charCodeAt(t.index - 1);
134032
134000
  else for (j = i - 1; j >= 0; j--) {
134033
134001
  if (tokens[j].type === "softbreak" || tokens[j].type === "hardbreak") break;
134034
134002
  if (!tokens[j].content) continue;
@@ -134036,7 +134004,7 @@ function process_inlines(tokens, state) {
134036
134004
  break;
134037
134005
  }
134038
134006
  let nextChar = 32;
134039
- if (pos < max) nextChar = text3.charCodeAt(pos);
134007
+ if (pos < max) nextChar = text4.charCodeAt(pos);
134040
134008
  else for (j = i + 1; j < tokens.length; j++) {
134041
134009
  if (tokens[j].type === "softbreak" || tokens[j].type === "hardbreak") break;
134042
134010
  if (!tokens[j].content) continue;
@@ -135371,7 +135339,7 @@ function isTerminatorChar(ch) {
135371
135339
  return false;
135372
135340
  }
135373
135341
  }
135374
- function text2(state, silent) {
135342
+ function text3(state, silent) {
135375
135343
  let pos = state.pos;
135376
135344
  while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) pos++;
135377
135345
  if (pos === state.pos) return false;
@@ -136045,7 +136013,7 @@ function fragments_join(state) {
136045
136013
  if (curr !== last) tokens.length = last;
136046
136014
  }
136047
136015
  var _rules = [
136048
- ["text", text2],
136016
+ ["text", text3],
136049
136017
  ["linkify", linkify],
136050
136018
  ["newline", newline],
136051
136019
  ["escape", escape2],
@@ -136681,8 +136649,8 @@ var markdownToElements = (input) => {
136681
136649
  const buffer = [];
136682
136650
  let tableCount = 0;
136683
136651
  const flushBuffer = () => {
136684
- const text3 = buffer.join("\n\n").replace(/\n{3,}/g, "\n\n").trim();
136685
- if (text3 !== "") elements.push({ tag: "markdown", content: text3 });
136652
+ const text4 = buffer.join("\n\n").replace(/\n{3,}/g, "\n\n").trim();
136653
+ if (text4 !== "") elements.push({ tag: "markdown", content: text4 });
136686
136654
  buffer.length = 0;
136687
136655
  };
136688
136656
  let index = 0;
@@ -136694,8 +136662,8 @@ var markdownToElements = (input) => {
136694
136662
  continue;
136695
136663
  }
136696
136664
  if (token.type === "heading_open") {
136697
- const text3 = (tokens[index + 1]?.content ?? "").replace(/^#{1,6}\s+/, "").trim();
136698
- if (text3 !== "") buffer.push(`**${text3}**`);
136665
+ const text4 = (tokens[index + 1]?.content ?? "").replace(/^#{1,6}\s+/, "").trim();
136666
+ if (text4 !== "") buffer.push(`**${text4}**`);
136699
136667
  index += 3;
136700
136668
  continue;
136701
136669
  }
@@ -136757,23 +136725,23 @@ var STATUS_TEMPLATE = {
136757
136725
  continued: "grey"
136758
136726
  };
136759
136727
  var encoder = new TextEncoder();
136760
- var stripAngleBrackets = (text3) => text3.replaceAll("<", "").replaceAll(">", "");
136761
- var truncateTail = (text3, t, maxBytes = MAX_CARD_BODY_BYTES) => {
136762
- if (encoder.encode(text3).length <= maxBytes) return text3;
136728
+ var stripAngleBrackets = (text4) => text4.replaceAll("<", "").replaceAll(">", "");
136729
+ var truncateTail = (text4, t, maxBytes = MAX_CARD_BODY_BYTES) => {
136730
+ if (encoder.encode(text4).length <= maxBytes) return text4;
136763
136731
  const marker = `${t("card.truncated", { count: 9999999 })}
136764
136732
  `;
136765
136733
  const budget = maxBytes - encoder.encode(marker).length;
136766
136734
  if (budget < 1) return "";
136767
136735
  const kept = [];
136768
136736
  let used = 0;
136769
- for (const char of Array.from(text3).toReversed()) {
136737
+ for (const char of Array.from(text4).toReversed()) {
136770
136738
  const size = encoder.encode(char).length;
136771
136739
  if (used + size > budget) break;
136772
136740
  used += size;
136773
136741
  kept.push(char);
136774
136742
  }
136775
136743
  const tail = kept.toReversed().join("");
136776
- const dropped = Array.from(text3).length - kept.length;
136744
+ const dropped = Array.from(text4).length - kept.length;
136777
136745
  return `${t("card.truncated", { count: dropped })}
136778
136746
  ${tail}`;
136779
136747
  };
@@ -136930,8 +136898,8 @@ var buildChoiceCard = (card) => {
136930
136898
  var import_node_sdk = __toESM(require_lib2(), 1);
136931
136899
 
136932
136900
  // src/larkPost.ts
136933
- var styledText = (text3, style) => {
136934
- let out = text3;
136901
+ var styledText = (text4, style) => {
136902
+ let out = text4;
136935
136903
  if (style?.includes("bold")) out = `**${out}**`;
136936
136904
  if (style?.includes("italic")) out = `*${out}*`;
136937
136905
  if (style?.includes("lineThrough")) out = `~~${out}~~`;
@@ -137015,18 +136983,18 @@ var serializePost = (content, botIds = /* @__PURE__ */ new Set()) => {
137015
136983
  placeholderByKey.set(key, placeholderOf(element, index));
137016
136984
  }
137017
136985
  }
137018
- const text4 = md2.replace(
136986
+ const text5 = md2.replace(
137019
136987
  /!\[(?:img|video|file)\]\(([^)]+)\)/g,
137020
136988
  (whole, rawKey) => placeholderByKey.get(rawKey.trim()) ?? whole
137021
136989
  );
137022
- return { text: text4, resources };
136990
+ return { text: text5, resources };
137023
136991
  }
137024
136992
  const paragraphs = (parsed.content ?? []).map(
137025
136993
  (row) => row.map((element) => serializeElement(element, indexOf.get(element) ?? null, botIds)).join("")
137026
136994
  );
137027
- const text3 = paragraphs.map((line) => line.trim()).filter((line) => line !== "").join("\n");
137028
- if (text3 === "" && resources.length === 0) return void 0;
137029
- return { text: text3, resources };
136995
+ const text4 = paragraphs.map((line) => line.trim()).filter((line) => line !== "").join("\n");
136996
+ if (text4 === "" && resources.length === 0) return void 0;
136997
+ return { text: text4, resources };
137030
136998
  };
137031
136999
 
137032
137000
  // src/larkInbound.ts
@@ -137099,8 +137067,8 @@ var readResource = (messageType, content) => {
137099
137067
  return null;
137100
137068
  };
137101
137069
  var readText = (content) => {
137102
- const text3 = readJson(content)?.["text"];
137103
- return typeof text3 === "string" ? text3 : null;
137070
+ const text4 = readJson(content)?.["text"];
137071
+ return typeof text4 === "string" ? text4 : null;
137104
137072
  };
137105
137073
  var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention = true) => {
137106
137074
  if (event.sender?.sender_type === "app") return null;
@@ -137135,9 +137103,9 @@ var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention
137135
137103
  const single = post === void 0 ? readResource(messageType, message.content) : null;
137136
137104
  const resources = post !== void 0 ? post.resources : single === null ? [] : [single];
137137
137105
  const raw = post !== void 0 ? post.text : messageType === "text" ? readText(message.content) : null;
137138
- const text3 = mentions.reduce((value2, mention) => value2.replaceAll(mention.key, ""), raw ?? "").trim();
137139
- if (text3.length === 0 && resources.length === 0) return null;
137140
- return { messageId, chatId, chatType, senderOpenId, text: text3, resources, inThread, ...topic };
137106
+ const text4 = mentions.reduce((value2, mention) => value2.replaceAll(mention.key, ""), raw ?? "").trim();
137107
+ if (text4.length === 0 && resources.length === 0) return null;
137108
+ return { messageId, chatId, chatType, senderOpenId, text: text4, resources, inThread, ...topic };
137141
137109
  };
137142
137110
  var fetchMessageResource = async (input) => {
137143
137111
  const url = `${LARK_BASE}/im/v1/messages/${encodeURIComponent(
@@ -137495,10 +137463,10 @@ var makeLarkAdapter = (deps) => {
137495
137463
  name: input.name,
137496
137464
  memberOpenIds: input.memberIds
137497
137465
  }),
137498
- sendText: async (binding, text3, options) => {
137466
+ sendText: async (binding, text4, options) => {
137499
137467
  const target2 = await sendTarget(binding);
137500
137468
  const receiveIdType = options?.targetKind === "user" ? "open_id" : "chat_id";
137501
- for (const chunk of splitForLark(text3)) {
137469
+ for (const chunk of splitForLark(text4)) {
137502
137470
  const messageId = await sendChatText({
137503
137471
  ...target2,
137504
137472
  receiveIdType,
@@ -137854,7 +137822,6 @@ var en_default = {
137854
137822
  turnFailedNoDetail: "This turn didn't finish. Reference {{ref}}. Send the message again; if it keeps failing, send /new to start a new conversation.",
137855
137823
  turnFailedBrief: "This turn didn't finish: {{detail}}\nSend the message again; if it keeps failing, send /new to start a new conversation.",
137856
137824
  turnFailedBriefNoDetail: "This turn didn't finish. Send the message again; if it keeps failing, send /new to start a new conversation.",
137857
- teamGone: "The team this chat was sending to no longer exists, so messages go to a normal session again.",
137858
137825
  attachmentReceived: "Got {{names}} ({{count}} waiting). Tell me what to do with them.",
137859
137826
  attachmentFailed: "Could not take {{name}}: {{reason}}.",
137860
137827
  attachmentReason: {
@@ -137922,10 +137889,8 @@ var en_default = {
137922
137889
  plainNotice: "Queued: this message goes out when the current reply finishes."
137923
137890
  },
137924
137891
  command: {
137925
- teamSelected: 'OK. From now on messages go to "{{title}}".',
137892
+ teamSelected: "OK. Each message now gives this project's team a goal. Send /thread to go back to a normal session.",
137926
137893
  threadSelected: "OK. From now on messages start a normal session.",
137927
- teamNotFound: 'No team is called "{{query}}", or more than one matches.',
137928
- noTeams: "There are no teams on this machine yet.",
137929
137894
  newSession: "OK. The next message starts a new session.",
137930
137895
  stopNoSession: "Nothing is running in this chat.",
137931
137896
  stopNoTurn: "No turn is running right now.",
@@ -137935,7 +137900,7 @@ var en_default = {
137935
137900
  stopped: "Stopped. The session is still there \u2014 just keep talking."
137936
137901
  },
137937
137902
  status: {
137938
- routedTeam: "Sent to: {{title}}",
137903
+ routedTeam: "Sent to: this project's team",
137939
137904
  routedThread: "Normal session",
137940
137905
  nothingRunning: "{{where}}. Nothing is running.",
137941
137906
  session: "Session: {{title}}",
@@ -137946,20 +137911,13 @@ var en_default = {
137946
137911
  project: "Project: {{title}}",
137947
137912
  noProject: "No project picked yet. Send /repo to pick one."
137948
137913
  },
137949
- targets: {
137950
- currentThread: "This chat is on a normal session.",
137951
- currentTeam: "Sent to: {{title}}",
137952
- noTeams: "There are no teams on this machine yet.",
137953
- teamList: "Teams you can pick:",
137954
- hint: "Use /team name to switch, /thread to go back to a normal session."
137955
- },
137956
137914
  help: {
137957
137915
  title: "Commands:",
137958
137916
  continue: "\xB7 /continue \u2014 resume sending after /stop or a failure paused it; the waiting messages go out",
137959
137917
  stop: "\xB7 /stop \u2014 stop the turn that is running; the session stays",
137960
137918
  status: "\xB7 /status \u2014 what is going on right now",
137961
137919
  new: "\xB7 /new \u2014 forget the current session; the next message starts a new one",
137962
- team: "\xB7 /team name \u2014 send the next messages to a team; /team alone lists the teams",
137920
+ team: "\xB7 /team \u2014 give this project's team a goal with each message; use /repo to pick the project first",
137963
137921
  thread: "\xB7 /thread \u2014 go back to a normal session",
137964
137922
  aliases: "Chinese shortcuts (\u505C / \u7EE7\u7EED\u53D1\u9001 / \u72B6\u6001 / \u65B0\u5BF9\u8BDD / \u4F1A\u8BDD\u5217\u8868 / \u5207\u6362\u4F1A\u8BDD / \u6362\u6A21\u578B / \u8BA1\u5212\u6A21\u5F0F / \u6362\u9879\u76EE / \u5EFA\u7FA4 / \u6362\u56E2\u961F / \u6362\u5BF9\u8BDD) work when the reply language is Chinese.",
137965
137923
  sessions: "\xB7 /sessions \u2014 list the sessions this bot opened for this chat's project",
@@ -138083,11 +138041,6 @@ var en_default = {
138083
138041
  title: "Pick a session",
138084
138042
  hint: "Tap one to switch to it."
138085
138043
  },
138086
- teams: {
138087
- title: "Pick a team",
138088
- hint: "Tap a team and the next messages go to it.",
138089
- unavailable: "Could not read the team list."
138090
- },
138091
138044
  models: {
138092
138045
  title: "Pick a model"
138093
138046
  },
@@ -138258,7 +138211,7 @@ var en_default = {
138258
138211
  model: "See or switch the model",
138259
138212
  plan: "Toggle plan mode",
138260
138213
  repo: "Pick the project this chat works on",
138261
- team: "Send the next messages to a team",
138214
+ team: "Give this project's team a goal with each message",
138262
138215
  thread: "Go back to a normal session",
138263
138216
  panel: "Open the command panel",
138264
138217
  help: "Show all commands"
@@ -138322,6 +138275,14 @@ var en_default = {
138322
138275
  removeConfirm: "Delete this target",
138323
138276
  removeFailed: "Couldn't delete this target."
138324
138277
  }
138278
+ },
138279
+ team: {
138280
+ noRoster: "This project has no team roster yet. Save a roster in the Teams tab and choose a lead first.",
138281
+ unavailable: "Could not read this project's team roster. Check that the Teams plugin is enabled and try again.",
138282
+ invalidGoal: "The goal is empty or too long. Edit your message and send it again.",
138283
+ startFailed: "Could not give this goal to the team lead. Try sending the message again.",
138284
+ startedUnnamed: "Handed to the team lead. Goal: {{goal}}",
138285
+ started: "Given to team lead {{name}}. Goal: {{goal}}"
138325
138286
  }
138326
138287
  };
138327
138288
 
@@ -138525,7 +138486,6 @@ var zh_CN_default = {
138525
138486
  turnFailedNoDetail: "\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u53C2\u8003\u53F7 {{ref}}\u3002\u53EF\u4EE5\u76F4\u63A5\u518D\u53D1\u4E00\u6B21\uFF1B\u4E00\u76F4\u4E0D\u884C\u5C31\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\u3002",
138526
138487
  turnFailedBrief: "\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\uFF1A{{detail}}\n\u53EF\u4EE5\u76F4\u63A5\u518D\u53D1\u4E00\u6B21\uFF1B\u4E00\u76F4\u4E0D\u884C\u5C31\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\u3002",
138527
138488
  turnFailedBriefNoDetail: "\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u53EF\u4EE5\u76F4\u63A5\u518D\u53D1\u4E00\u6B21\uFF1B\u4E00\u76F4\u4E0D\u884C\u5C31\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\u3002",
138528
- teamGone: "\u8FD9\u4E2A\u804A\u5929\u539F\u6765\u6D3E\u7ED9\u7684\u961F\u5DF2\u7ECF\u4E0D\u5728\u4E86\uFF0C\u63A5\u4E0B\u6765\u6539\u56DE\u666E\u901A\u4F1A\u8BDD\u3002",
138529
138489
  attachmentReceived: "\u6536\u5230 {{names}}\uFF08\u73B0\u6709 {{count}} \u4E2A\u5F85\u5904\u7406\uFF09\u3002\u8BF4\u4E00\u53E5\u60F3\u8BA9\u6211\u600E\u4E48\u5904\u7406\u3002",
138530
138490
  attachmentFailed: "\u6CA1\u80FD\u6536\u4E0B {{name}}\uFF1A{{reason}}\u3002",
138531
138491
  attachmentReason: {
@@ -138593,10 +138553,8 @@ var zh_CN_default = {
138593
138553
  plainNotice: "\u5DF2\u6392\u961F\uFF1A\u5F53\u524D\u8FD9\u4E00\u8F6E\u56DE\u590D\u7ED3\u675F\u540E\u53D1\u51FA\u3002"
138594
138554
  },
138595
138555
  command: {
138596
- teamSelected: "\u597D\uFF0C\u63A5\u4E0B\u6765\u6D3E\u7ED9\u300C{{title}}\u300D\u3002",
138556
+ teamSelected: "\u597D\uFF0C\u63A5\u4E0B\u6765\u6BCF\u6761\u6D88\u606F\u90FD\u7ED9\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F\u5F00\u4E00\u4E2A\u76EE\u6807\u3002\u53D1 /thread \u56DE\u5230\u666E\u901A\u4F1A\u8BDD\u3002",
138597
138557
  threadSelected: "\u597D\uFF0C\u63A5\u4E0B\u6765\u5F00\u666E\u901A\u4F1A\u8BDD\u3002",
138598
- teamNotFound: "\u6CA1\u627E\u5230\u53EB\u300C{{query}}\u300D\u7684\u961F\uFF0C\u4E5F\u53EF\u80FD\u662F\u4E0D\u6B62\u4E00\u652F\u5BF9\u5F97\u4E0A\u3002",
138599
- noTeams: "\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD8\u6CA1\u6709\u56E2\u961F\u3002",
138600
138558
  newSession: "\u597D\uFF0C\u4E0B\u4E00\u53E5\u8BDD\u5F00\u4E00\u6761\u65B0\u4F1A\u8BDD\u3002",
138601
138559
  stopNoSession: "\u8FD9\u4E2A\u804A\u5929\u73B0\u5728\u6CA1\u6709\u5728\u8DD1\u7684\u6D3B\u513F\u3002",
138602
138560
  stopNoTurn: "\u73B0\u5728\u6CA1\u6709\u5728\u8DD1\u7684\u4E00\u8F6E\u3002",
@@ -138606,7 +138564,7 @@ var zh_CN_default = {
138606
138564
  stopped: "\u505C\u4E86\u3002\u4F1A\u8BDD\u8FD8\u5728\uFF0C\u63A5\u7740\u8BF4\u5C31\u884C\u3002"
138607
138565
  },
138608
138566
  status: {
138609
- routedTeam: "\u6D3E\u7ED9\uFF1A{{title}}",
138567
+ routedTeam: "\u6D3E\u7ED9\uFF1A\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F",
138610
138568
  routedThread: "\u666E\u901A\u4F1A\u8BDD",
138611
138569
  nothingRunning: "{{where}}\u3002\u73B0\u5728\u6CA1\u6709\u5728\u8DD1\u7684\u6D3B\u513F\u3002",
138612
138570
  session: "\u4F1A\u8BDD\uFF1A{{title}}",
@@ -138617,20 +138575,13 @@ var zh_CN_default = {
138617
138575
  project: "\u9879\u76EE\uFF1A{{title}}",
138618
138576
  noProject: "\u8FD8\u6CA1\u9009\u9879\u76EE\u3002\u53D1 /repo \u9009\u4E00\u4E2A\u3002"
138619
138577
  },
138620
- targets: {
138621
- currentThread: "\u73B0\u5728\u8FD9\u4E2A\u804A\u5929\u5F00\u7684\u662F\u666E\u901A\u4F1A\u8BDD\u3002",
138622
- currentTeam: "\u73B0\u5728\u6D3E\u7ED9\uFF1A{{title}}",
138623
- noTeams: "\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD8\u6CA1\u6709\u56E2\u961F\u3002",
138624
- teamList: "\u53EF\u9009\u7684\u961F\uFF1A",
138625
- hint: "\u7528 /team \u961F\u540D \u5207\u6362\uFF0C/thread \u5207\u56DE\u666E\u901A\u4F1A\u8BDD\u3002"
138626
- },
138627
138578
  help: {
138628
138579
  title: "\u80FD\u7528\u7684\u547D\u4EE4\uFF1A",
138629
138580
  continue: "\xB7 /continue \u2014\u2014 /stop \u6216\u51FA\u9519\u6682\u505C\u4E86\u53D1\u9001\u4E4B\u540E\uFF0C\u7528\u5B83\u6062\u590D\uFF0C\u6392\u7740\u7684\u6D88\u606F\u7EE7\u7EED\u53D1\u51FA",
138630
138581
  stop: "\xB7 /stop \u2014\u2014 \u505C\u6389\u6B63\u5728\u8DD1\u7684\u8FD9\u4E00\u8F6E\uFF0C\u4F1A\u8BDD\u7559\u7740",
138631
138582
  status: "\xB7 /status \u2014\u2014 \u73B0\u5728\u5728\u5E72\u4EC0\u4E48",
138632
138583
  new: "\xB7 /new \u2014\u2014 \u5FD8\u6389\u5F53\u524D\u4F1A\u8BDD\uFF0C\u4E0B\u4E00\u53E5\u5F00\u65B0\u7684",
138633
- team: "\xB7 /team \u961F\u540D \u2014\u2014 \u628A\u63A5\u4E0B\u6765\u7684\u6D3B\u6D3E\u7ED9\u4E00\u652F\u961F\uFF1B/team \u4E0D\u5E26\u540D\u5B57\u770B\u6709\u54EA\u4E9B\u961F",
138584
+ team: "\xB7 /team \u2014\u2014 \u6BCF\u6761\u6D88\u606F\u90FD\u7ED9\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F\u5F00\u4E00\u4E2A\u76EE\u6807\uFF1B\u5148\u7528 /repo \u9009\u9879\u76EE",
138634
138585
  thread: "\xB7 /thread \u2014\u2014 \u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
138635
138586
  aliases: "\u4E2D\u6587\u4E5F\u884C\uFF1A\u505C / \u7EE7\u7EED\u53D1\u9001 / \u72B6\u6001 / \u65B0\u5BF9\u8BDD / \u4F1A\u8BDD\u5217\u8868 / \u5207\u6362\u4F1A\u8BDD / \u6362\u6A21\u578B / \u8BA1\u5212\u6A21\u5F0F / \u6362\u9879\u76EE / \u5EFA\u7FA4 / \u6362\u56E2\u961F / \u6362\u5BF9\u8BDD\u3002",
138636
138587
  sessions: "\xB7 /sessions \u2014\u2014 \u5217\u51FA\u672C\u673A\u5668\u4EBA\u4E3A\u8FD9\u4E2A\u804A\u5929\u7684\u9879\u76EE\u5F00\u8FC7\u7684\u4F1A\u8BDD",
@@ -138754,11 +138705,6 @@ var zh_CN_default = {
138754
138705
  title: "\u9009\u4E00\u6761\u4F1A\u8BDD",
138755
138706
  hint: "\u70B9\u4E00\u6761\u5207\u8FC7\u53BB\u3002"
138756
138707
  },
138757
- teams: {
138758
- title: "\u9009\u4E00\u652F\u961F",
138759
- hint: "\u70B9\u4E00\u652F\u961F\uFF0C\u63A5\u4E0B\u6765\u7684\u6D3B\u6D3E\u7ED9\u5B83\u3002",
138760
- unavailable: "\u8BFB\u4E0D\u5230\u56E2\u961F\u5217\u8868\u3002"
138761
- },
138762
138708
  models: {
138763
138709
  title: "\u9009\u6A21\u578B"
138764
138710
  },
@@ -138929,7 +138875,7 @@ var zh_CN_default = {
138929
138875
  model: "\u770B\u6216\u6362\u6A21\u578B",
138930
138876
  plan: "\u5F00\u5173\u8BA1\u5212\u6A21\u5F0F",
138931
138877
  repo: "\u9009\u8FD9\u4E2A\u804A\u5929\u5728\u54EA\u4E2A\u9879\u76EE\u4E0A\u5E72\u6D3B",
138932
- team: "\u628A\u63A5\u4E0B\u6765\u7684\u8BDD\u53D1\u7ED9\u4E00\u652F\u56E2\u961F",
138878
+ team: "\u6BCF\u6761\u6D88\u606F\u90FD\u7ED9\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F\u5F00\u4E00\u4E2A\u76EE\u6807",
138933
138879
  thread: "\u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
138934
138880
  panel: "\u6253\u5F00\u547D\u4EE4\u9762\u677F",
138935
138881
  help: "\u5217\u51FA\u5168\u90E8\u547D\u4EE4"
@@ -138993,6 +138939,14 @@ var zh_CN_default = {
138993
138939
  removeConfirm: "\u5220\u9664\u8FD9\u4E2A\u76EE\u6807",
138994
138940
  removeFailed: "\u8FD9\u4E2A\u76EE\u6807\u6CA1\u5220\u6389\u3002"
138995
138941
  }
138942
+ },
138943
+ team: {
138944
+ noRoster: "\u8FD9\u4E2A\u9879\u76EE\u8FD8\u6CA1\u6709\u56E2\u961F\u540D\u5355\uFF0C\u5148\u5728 Teams \u6807\u7B7E\u91CC\u4FDD\u5B58\u540D\u5355\u5E76\u9009\u4E00\u540D\u8D1F\u8D23\u4EBA\u3002",
138945
+ unavailable: "\u6682\u65F6\u8BFB\u4E0D\u5230\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F\u540D\u5355\uFF0C\u8BF7\u786E\u8BA4 Teams \u63D2\u4EF6\u5DF2\u542F\u7528\u540E\u91CD\u8BD5\u3002",
138946
+ invalidGoal: "\u76EE\u6807\u4E3A\u7A7A\u6216\u592A\u957F\uFF0C\u8BF7\u4FEE\u6539\u6D88\u606F\u540E\u91CD\u53D1\u3002",
138947
+ startFailed: "\u6CA1\u80FD\u628A\u76EE\u6807\u4EA4\u7ED9\u8D1F\u8D23\u4EBA\uFF0C\u8BF7\u91CD\u53D1\u8FD9\u6761\u6D88\u606F\u518D\u8BD5\u3002",
138948
+ startedUnnamed: "\u5DF2\u4EA4\u7ED9\u8D1F\u8D23\u4EBA\uFF0C\u76EE\u6807\uFF1A{{goal}}",
138949
+ started: "\u5DF2\u4EA4\u7ED9\u8D1F\u8D23\u4EBA {{name}}\uFF0C\u76EE\u6807\uFF1A{{goal}}"
138996
138950
  }
138997
138951
  };
138998
138952
 
@@ -139015,8 +138969,8 @@ var interpolate = (template, params) => params === void 0 ? template : template.
139015
138969
  var makeTranslate = (language) => {
139016
138970
  const catalog = CATALOGS[language];
139017
138971
  const optional = (key, params) => {
139018
- const text3 = lookup(catalog, key);
139019
- return text3 === void 0 ? void 0 : interpolate(text3, params);
138972
+ const text4 = lookup(catalog, key);
138973
+ return text4 === void 0 ? void 0 : interpolate(text4, params);
139020
138974
  };
139021
138975
  return Object.assign(
139022
138976
  (key, params) => optional(key, params) ?? key,
@@ -139085,9 +139039,8 @@ var makeModelPlan = (core, deps) => {
139085
139039
  const threadId = chatOf(core.state, chatKey).threadId;
139086
139040
  if (threadId !== null && await threadStillUsable(binding, threadId)) {
139087
139041
  try {
139088
- await host.commands.dispatch({
139089
- type: "thread.meta.update",
139090
- commandId: crypto.randomUUID(),
139042
+ await host.threads.update({
139043
+ requestId: crypto.randomUUID(),
139091
139044
  threadId,
139092
139045
  modelSelection: selection
139093
139046
  });
@@ -139131,22 +139084,16 @@ var notificationChatKeys = (state, threadId, projectId) => {
139131
139084
 
139132
139085
  // src/threadMessages.ts
139133
139086
  import {
139134
- isThreadNotFound
139087
+ isThreadNotFound,
139088
+ threadMessagesNewestFirst
139135
139089
  } from "@ycodium-ai/plugin-api";
139136
139090
  var PAGE_SIZE = 20;
139137
139091
  async function* newestFirst(threads, threadId) {
139138
- let cursor = null;
139139
- do {
139140
- let page;
139141
- try {
139142
- page = await threads.messages.list({ threadId, limit: PAGE_SIZE, cursor });
139143
- } catch (error) {
139144
- if (isThreadNotFound(error)) return;
139145
- throw error;
139146
- }
139147
- yield* page.items;
139148
- cursor = page.nextCursor;
139149
- } while (cursor !== null);
139092
+ try {
139093
+ yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
139094
+ } catch (error) {
139095
+ if (!isThreadNotFound(error)) throw error;
139096
+ }
139150
139097
  }
139151
139098
  async function attachmentsOf(threads, threadId, message) {
139152
139099
  const collected = [...message.attachments ?? []];
@@ -139191,7 +139138,6 @@ var outcomeOfSession = (status) => {
139191
139138
  if (status === "interrupted" || status === "stopped") return "stopped";
139192
139139
  return "done";
139193
139140
  };
139194
- var outcomeOfTeamRun = (state) => state === "settled" ? "done" : state === "failed" ? "failed" : "stopped";
139195
139141
 
139196
139142
  // src/notifications.ts
139197
139143
  var THREAD_PROJECT_CACHE_LIMIT = 256;
@@ -139217,7 +139163,8 @@ var makeNotifications = (core, deps) => {
139217
139163
  const binding = bindingForChatKey(chatKey);
139218
139164
  return binding === void 0 ? [] : [binding];
139219
139165
  });
139220
- const streamsTo = (binding, threadId) => adapterFor(binding.platform)?.turnCards !== void 0 && chatOf(core.state, chatKeyOf(binding)).threadId === threadId;
139166
+ const streamsTo = (binding, threadId) => adapterFor(binding.platform)?.turnCards !== void 0 && owns(binding, threadId);
139167
+ const owns = (binding, threadId) => chatOfThread(core.state, threadId) === chatKeyOf(binding);
139221
139168
  const threadsWithSomethingToReport = /* @__PURE__ */ new Set();
139222
139169
  host.reactor({
139223
139170
  name: "im.assistant-messages",
@@ -139251,13 +139198,12 @@ var makeNotifications = (core, deps) => {
139251
139198
  if (thread !== null && final !== void 0) {
139252
139199
  const attachments = await attachmentsOf(host.threads, threadId, final);
139253
139200
  for (const binding of reporters) {
139254
- const text3 = streamsTo(binding, threadId) ? "" : `${thread.title}
139201
+ const text4 = streamsTo(binding, threadId) ? "" : `${thread.title}
139255
139202
 
139256
139203
  ${final.text}`;
139257
- const owns = chatOf(core.state, chatKeyOf(binding)).threadId === threadId;
139258
139204
  await deliver(
139259
- owns ? await anchors.anchored(binding, threadId, final.turnId) : binding,
139260
- text3,
139205
+ owns(binding, threadId) ? await anchors.anchored(binding, threadId, final.turnId) : binding,
139206
+ text4,
139261
139207
  attachments
139262
139208
  );
139263
139209
  }
@@ -139338,9 +139284,9 @@ var PANEL_COMMANDS = [
139338
139284
  id: "team",
139339
139285
  category: "target",
139340
139286
  line: "/team",
139341
- kind: "showTargets",
139287
+ kind: "selectTeam",
139342
139288
  labelKey: "panel.cmd.team",
139343
- action: { op: "open", arg: "teams" }
139289
+ action: { op: "run", arg: "team" }
139344
139290
  },
139345
139291
  {
139346
139292
  id: "thread",
@@ -139404,12 +139350,7 @@ var panelCommandsFor = (mode = "default") => mode === "minimal" ? PANEL_COMMANDS
139404
139350
  var PANEL_PAGE_SIZE = 8;
139405
139351
  var PANEL_CARD_LIMIT = 200;
139406
139352
  var LABEL_MAX_CHARS = 60;
139407
- var PICK_KINDS = /* @__PURE__ */ new Set([
139408
- "sessions",
139409
- "teams",
139410
- "models",
139411
- "projects"
139412
- ]);
139353
+ var PICK_KINDS = /* @__PURE__ */ new Set(["sessions", "models", "projects"]);
139413
139354
  var clip2 = (label) => {
139414
139355
  const chars = Array.from(label);
139415
139356
  return chars.length <= LABEL_MAX_CHARS ? label : `${chars.slice(0, LABEL_MAX_CHARS - 1).join("")}\u2026`;
@@ -139439,10 +139380,10 @@ var makePanelController = (deps) => {
139439
139380
  action: { op, arg },
139440
139381
  ...danger === true ? { danger } : {}
139441
139382
  });
139442
- const busyCard = (title, text3) => ({
139383
+ const busyCard = (title, text4) => ({
139443
139384
  title,
139444
139385
  tone: "busy",
139445
- text: text3,
139386
+ text: text4,
139446
139387
  groups: [],
139447
139388
  nav: []
139448
139389
  });
@@ -139519,16 +139460,6 @@ ${t("panel.projects.hint")}`;
139519
139460
  )
139520
139461
  });
139521
139462
  }
139522
- case "teams":
139523
- return pickerCard({
139524
- kind: "teams",
139525
- page: view.page,
139526
- depth,
139527
- text: view.teams === null ? t("panel.teams.unavailable") : view.teams.length === 0 ? t("command.noTeams") : t("panel.teams.hint"),
139528
- items: (view.teams ?? []).map(
139529
- (team) => button(team.title, "pick", `teams:${team.teamId}`)
139530
- )
139531
- });
139532
139463
  case "projects":
139533
139464
  return pickerCard({
139534
139465
  kind: "projects",
@@ -139582,17 +139513,15 @@ ${t("panel.projects.hint")}`;
139582
139513
  }
139583
139514
  }
139584
139515
  });
139585
- const placeholder = (entry, title, text3) => {
139516
+ const placeholder = (entry, title, text4) => {
139586
139517
  void post(entry.cardId, async () => {
139587
- await deps.surface(entry.chatKey)?.update(entry.cardId, busyCard(title, text3));
139518
+ await deps.surface(entry.chatKey)?.update(entry.cardId, busyCard(title, text4));
139588
139519
  });
139589
139520
  };
139590
139521
  const loadView = async (chatKey, kind) => {
139591
139522
  switch (kind) {
139592
139523
  case "sessions":
139593
139524
  return { kind, page: 0, rows: await deps.loadSessions(chatKey) };
139594
- case "teams":
139595
- return { kind, page: 0, teams: await deps.loadTeams(chatKey) };
139596
139525
  case "models":
139597
139526
  return { kind, page: 0, models: await deps.loadModels(chatKey) };
139598
139527
  case "projects":
@@ -139716,7 +139645,7 @@ ${t("panel.projects.hint")}`;
139716
139645
  return null;
139717
139646
  case "page": {
139718
139647
  const page = Number(arg);
139719
- if ((top.kind === "sessions" || top.kind === "teams" || top.kind === "models" || top.kind === "projects") && Number.isInteger(page) && page >= 0) {
139648
+ if ((top.kind === "sessions" || top.kind === "models" || top.kind === "projects") && Number.isInteger(page) && page >= 0) {
139720
139649
  navigate(entry, () => {
139721
139650
  entry.stack[entry.stack.length - 1] = { ...top, page };
139722
139651
  });
@@ -139739,7 +139668,7 @@ ${t("panel.projects.hint")}`;
139739
139668
  case "pick": {
139740
139669
  const split = arg.indexOf(":");
139741
139670
  const key = split < 0 ? "" : arg.slice(split + 1);
139742
- const line = top.kind === "sessions" && arg.startsWith("sessions:") ? top.rows.find((row) => row.threadId === key) === void 0 ? null : `/resume ${key}` : top.kind === "teams" && arg.startsWith("teams:") ? top.teams?.find((team) => team.teamId === key) === void 0 ? null : `/team ${key}` : top.kind === "models" && arg.startsWith("models:") ? top.models?.choices.find(
139671
+ const line = top.kind === "sessions" && arg.startsWith("sessions:") ? top.rows.find((row) => row.threadId === key) === void 0 ? null : `/resume ${key}` : top.kind === "models" && arg.startsWith("models:") ? top.models?.choices.find(
139743
139672
  (choice) => `${choice.instanceId}/${choice.model}` === key
139744
139673
  ) === void 0 ? null : `/model ${key}` : top.kind === "projects" && arg.startsWith("projects:") ? top.rows.find((row) => row.projectId === key) === void 0 ? null : `/repo ${key}` : null;
139745
139674
  if (line === null) {
@@ -139766,7 +139695,6 @@ var makePanelWiring = (core, deps) => {
139766
139695
  const { host, t, adapterFor, deliver, bindingOf: bindingOf2, bindingForChatKey } = core;
139767
139696
  const { enqueueForChat, handleCommand } = deps;
139768
139697
  const { sessionRowsFor, listedByChat } = deps.sessions;
139769
- const { fetchTeams } = deps.teams;
139770
139698
  const { currentModelOf } = deps.modelPlan;
139771
139699
  const { projectRowsFor, listedProjectsByChat } = deps.rows;
139772
139700
  const panel = makePanelController({
@@ -139792,10 +139720,6 @@ var makePanelWiring = (core, deps) => {
139792
139720
  listedByChat.set(chatKey, listedThreadIds(rows));
139793
139721
  return rows;
139794
139722
  },
139795
- loadTeams: async (chatKey) => {
139796
- const binding = bindingForChatKey(chatKey);
139797
- return binding === void 0 ? null : fetchTeams(binding);
139798
- },
139799
139723
  loadModels: async (chatKey) => {
139800
139724
  const binding = bindingForChatKey(chatKey);
139801
139725
  const instances = await host.providers.listInstances().catch(() => null);
@@ -139811,7 +139735,7 @@ var makePanelWiring = (core, deps) => {
139811
139735
  runLine: async (chatKey, line) => {
139812
139736
  const binding = bindingForChatKey(chatKey);
139813
139737
  if (binding === void 0) return;
139814
- await handleCommand(binding, line, await fetchTeams(binding) ?? []);
139738
+ await handleCommand(binding, line);
139815
139739
  },
139816
139740
  sendHelpText: async (chatKey) => {
139817
139741
  const binding = bindingForChatKey(chatKey);
@@ -139902,12 +139826,12 @@ var makeFailureNotices = (core) => {
139902
139826
  const reference2 = diagnosticRef("msg");
139903
139827
  core.host.log.warn("chat turn failed", { threadId, reference: reference2 });
139904
139828
  const said = reasonOf2(detail);
139905
- const text3 = said === "" ? core.t("reply.turnFailedNoDetail", { ref: reference2 }) : core.t("reply.turnFailed", { detail: said, ref: reference2 });
139906
- return text3;
139829
+ const text4 = said === "" ? core.t("reply.turnFailedNoDetail", { ref: reference2 }) : core.t("reply.turnFailed", { detail: said, ref: reference2 });
139830
+ return text4;
139907
139831
  },
139908
139832
  /** 正在画的那一轮的卡会说这次失败:寄存给它。 */
139909
- holdForCard: (threadId, turnId, text3) => {
139910
- heldForCard.set(threadId, { turnId, text: text3 });
139833
+ holdForCard: (threadId, turnId, text4) => {
139834
+ heldForCard.set(threadId, { turnId, text: text4 });
139911
139835
  },
139912
139836
  /**
139913
139837
  * 卡收尾(无论怎么收的都调):清掉这条会话的寄存。失败收尾时,寄存是这一轮的就用它(同一个号),
@@ -139943,8 +139867,8 @@ var STEP_KIND_BY_ITEM_TYPE = {
139943
139867
  };
139944
139868
  var stepKindOf = (itemType) => STEP_KIND_BY_ITEM_TYPE[itemType] ?? "tool";
139945
139869
  var TURN_TITLE_MAX_CHARS = 40;
139946
- var turnTitleOf = (text3) => {
139947
- const oneLine = text3.replace(/\s+/g, " ").trim();
139870
+ var turnTitleOf = (text4) => {
139871
+ const oneLine = text4.replace(/\s+/g, " ").trim();
139948
139872
  return oneLine.length <= TURN_TITLE_MAX_CHARS ? oneLine : `${oneLine.slice(0, TURN_TITLE_MAX_CHARS)}\u2026`;
139949
139873
  };
139950
139874
  var buildTurnView = (input) => {
@@ -139952,7 +139876,7 @@ var buildTurnView = (input) => {
139952
139876
  const steps = [];
139953
139877
  if (progress.thinking.active || progress.thinking.chars > 0) steps.push("think");
139954
139878
  for (const tool of progress.tools) steps.push(stepKindOf(tool.itemType));
139955
- const body = progress.segments.map((segment) => input.texts.get(segment.messageId) ?? "").filter((text3) => text3.trim() !== "").join("\n\n");
139879
+ const body = progress.segments.map((segment) => input.texts.get(segment.messageId) ?? "").filter((text4) => text4.trim() !== "").join("\n\n");
139956
139880
  const runningTool = progress.tools.findLast((tool) => tool.status === "running");
139957
139881
  const running = input.status === "working" && runningTool !== void 0 && runningTool.label !== "" ? runningTool.label : null;
139958
139882
  return {
@@ -140005,9 +139929,9 @@ var makeTurnCards = (deps) => {
140005
139929
  texts.set(segment.messageId, known);
140006
139930
  continue;
140007
139931
  }
140008
- const text3 = await deps.readText(segment.messageId) ?? "";
140009
- texts.set(segment.messageId, text3);
140010
- if (!segment.streaming) live?.settledTexts.set(segment.messageId, text3);
139932
+ const text4 = await deps.readText(segment.messageId) ?? "";
139933
+ texts.set(segment.messageId, text4);
139934
+ if (!segment.streaming) live?.settledTexts.set(segment.messageId, text4);
140011
139935
  }
140012
139936
  return texts;
140013
139937
  };
@@ -140267,8 +140191,8 @@ var makeReplyCards = (core, failures, anchors) => {
140267
140191
  fallback: async (threadId, turnId, chatKey, view) => {
140268
140192
  const binding = bindingForChatKey(chatKey);
140269
140193
  if (binding === void 0) return;
140270
- const text3 = [view.body, view.errorText ?? ""].filter((part) => part !== "").join("\n\n");
140271
- await deliver(await anchors.anchored(binding, threadId, turnId), text3);
140194
+ const text4 = [view.body, view.errorText ?? ""].filter((part) => part !== "").join("\n\n");
140195
+ await deliver(await anchors.anchored(binding, threadId, turnId), text4);
140272
140196
  },
140273
140197
  schedule: (run, delayMs) => {
140274
140198
  const timer = setTimeout(run, delayMs);
@@ -140347,8 +140271,8 @@ var makeDeliverySender = (core, config2) => {
140347
140271
  };
140348
140272
 
140349
140273
  // src/sendFile.ts
140350
- var failure = (code2, text3) => ({
140351
- text: text3,
140274
+ var failure = (code2, text4) => ({
140275
+ text: text4,
140352
140276
  isError: true,
140353
140277
  errorCode: code2
140354
140278
  });
@@ -140501,15 +140425,14 @@ var makeSessions = (core) => {
140501
140425
  const pendingAttachByChat = /* @__PURE__ */ new Map();
140502
140426
  const rowFromThread = (thread, chatKey, origin) => {
140503
140427
  if (thread.archivedAt != null) return null;
140428
+ const owner = chatOfThread(core.state, thread.threadId);
140504
140429
  return {
140505
140430
  threadId: thread.threadId,
140506
140431
  title: thread.title,
140507
140432
  updatedAt: thread.updatedAt,
140508
140433
  running: isSessionRunning(thread.sessionStatus),
140509
140434
  current: chatOf(core.state, chatKey).threadId === thread.threadId,
140510
- elsewhere: Object.entries(core.state.chats).some(
140511
- ([otherKey, record2]) => otherKey !== chatKey && record2.threadId === thread.threadId
140512
- ),
140435
+ elsewhere: owner !== void 0 && owner !== chatKey,
140513
140436
  origin
140514
140437
  };
140515
140438
  };
@@ -140638,51 +140561,76 @@ var makeSessions = (core) => {
140638
140561
  return { listedByChat, sessionRowsFor, showSessions, resumeSession };
140639
140562
  };
140640
140563
 
140641
- // src/teamRuns.ts
140642
- var makeTeamRuns = (core, deps) => {
140643
- const { host, deliver } = core;
140644
- const { clearWorking } = deps;
140645
- const chatByRun = /* @__PURE__ */ new Map();
140646
- const fetchTeams = async (binding) => binding.projectId === "" ? [] : host.plugins.invoke({
140647
- pluginId: "teams",
140648
- command: "choices",
140649
- payload: { projectId: binding.projectId }
140650
- }).then(
140651
- (result) => Array.isArray(result) ? result.flatMap(
140652
- (row) => typeof row === "object" && row !== null && typeof row.teamId === "string" && typeof row.title === "string" ? [{ teamId: row.teamId, title: row.title }] : []
140653
- ) : null
140654
- ).catch(() => null);
140655
- const startTeamRun = async (binding, teamId, text3) => {
140656
- const commandId = crypto.randomUUID();
140657
- const runId = `run:${commandId}`;
140658
- chatByRun.set(runId, binding);
140564
+ // src/teamGoals.ts
140565
+ import * as NodeCrypto2 from "node:crypto";
140566
+ var isRecord2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
140567
+ var teamGoalRequestId = (binding, messageId) => {
140568
+ const identity = JSON.stringify([
140569
+ "im",
140570
+ binding.rowId,
140571
+ binding.platform,
140572
+ binding.chatId,
140573
+ messageId
140574
+ ]);
140575
+ return NodeCrypto2.createHash("sha256").update(identity).digest("hex");
140576
+ };
140577
+ var makeTeamGoals = (core) => {
140578
+ const { host, t, deliver, commit } = core;
140579
+ const hasRosterFor = async (binding) => {
140659
140580
  try {
140660
- await host.plugins.invoke({
140661
- pluginId: "teams",
140662
- command: "run",
140581
+ const roster = await host.plugins.invoke({
140582
+ pluginId: "team",
140583
+ command: "roster",
140584
+ payload: { projectId: binding.projectId }
140585
+ });
140586
+ if (roster === null) await deliver(binding, t("team.noRoster"));
140587
+ return roster !== null;
140588
+ } catch (error) {
140589
+ host.log.warn("chat could not read the team roster", { error: describeError(error) });
140590
+ await deliver(binding, t("team.unavailable"));
140591
+ return false;
140592
+ }
140593
+ };
140594
+ const startTeamGoal = async (binding, message) => {
140595
+ try {
140596
+ const result = await host.plugins.invoke({
140597
+ pluginId: "team",
140598
+ command: "startGoal",
140663
140599
  payload: {
140664
- commandId,
140665
- teamId,
140666
140600
  projectId: binding.projectId,
140667
- goal: text3
140601
+ goal: message.text,
140602
+ requestId: teamGoalRequestId(binding, message.messageId)
140668
140603
  }
140669
140604
  });
140605
+ if (isRecord2(result) && result._tag === "TeamGoalRejection") {
140606
+ await deliver(
140607
+ binding,
140608
+ t(
140609
+ result.code === "no-roster" ? "team.noRoster" : result.code === "invalid-goal" ? "team.invalidGoal" : "team.startFailed"
140610
+ )
140611
+ );
140612
+ return null;
140613
+ }
140614
+ if (!isRecord2(result) || typeof result.leadThreadId !== "string" || result.leadThreadId === "" || result.leadName !== null && typeof result.leadName !== "string") {
140615
+ throw new Error("team startGoal returned an invalid result");
140616
+ }
140617
+ commit("team-goal-started", { chatKey: chatKeyOf(binding), threadId: result.leadThreadId });
140618
+ await deliver(
140619
+ binding,
140620
+ typeof result.leadName === "string" ? t("team.started", { name: result.leadName, goal: message.text.trim() }) : t("team.startedUnnamed", { goal: message.text.trim() })
140621
+ );
140622
+ host.log.info("chat started a team goal", {
140623
+ bot: binding.displayName,
140624
+ threadId: result.leadThreadId
140625
+ });
140626
+ return result.leadThreadId;
140670
140627
  } catch (error) {
140671
- chatByRun.delete(runId);
140672
- throw error;
140628
+ host.log.warn("chat could not start the team goal", { error: describeError(error) });
140629
+ await deliver(binding, t("team.startFailed"));
140630
+ return null;
140673
140631
  }
140674
- host.log.info("chat started a team run", { bot: binding.displayName, teamId, runId });
140675
140632
  };
140676
- host.events.on("teams.run-ended", async (event) => {
140677
- const runId = event.data.runId;
140678
- if (typeof runId !== "string") return;
140679
- const binding = chatByRun.get(runId);
140680
- if (binding === void 0) return;
140681
- chatByRun.delete(runId);
140682
- await clearWorking(binding, chatKeyOf(binding), outcomeOfTeamRun(event.data.state));
140683
- await deliver(binding, event.summary);
140684
- });
140685
- return { fetchTeams, startTeamRun };
140633
+ return { hasRosterFor, startTeamGoal };
140686
140634
  };
140687
140635
 
140688
140636
  // src/telegramApi.ts
@@ -140776,19 +140724,19 @@ var unsupportedTypeOf = (message) => {
140776
140724
  return null;
140777
140725
  };
140778
140726
  var TELEGRAM_DOWNLOAD_LIMIT_BYTES = 20 * 1024 * 1024;
140779
- var splitForTelegram = (text3, limit = TELEGRAM_TEXT_MAX_CHARS) => splitMessage(text3, limit);
140727
+ var splitForTelegram = (text4, limit = TELEGRAM_TEXT_MAX_CHARS) => splitMessage(text4, limit);
140780
140728
  var nextOffset = (updates, current) => updates.reduce((offset, update) => Math.max(offset, update.update_id + 1), current);
140781
- var commandForBot = (text3, botUsername) => {
140782
- const match = text3.match(/^(\/[A-Za-z0-9_]+)@([A-Za-z0-9_]+)(?=\s|$)/);
140783
- if (match === null) return text3;
140729
+ var commandForBot = (text4, botUsername) => {
140730
+ const match = text4.match(/^(\/[A-Za-z0-9_]+)@([A-Za-z0-9_]+)(?=\s|$)/);
140731
+ if (match === null) return text4;
140784
140732
  const [whole, command = "", addressee = ""] = match;
140785
140733
  if (botUsername !== null && addressee.toLowerCase() !== botUsername.toLowerCase()) {
140786
140734
  return null;
140787
140735
  }
140788
- return command + text3.slice(whole.length);
140736
+ return command + text4.slice(whole.length);
140789
140737
  };
140790
- var mentionedNames = (text3) => Array.from(
140791
- text3.matchAll(/(?<![\w@])@([A-Za-z0-9_]{3,})/g),
140738
+ var mentionedNames = (text4) => Array.from(
140739
+ text4.matchAll(/(?<![\w@])@([A-Za-z0-9_]{3,})/g),
140792
140740
  (match) => (match[1] ?? "").toLowerCase()
140793
140741
  );
140794
140742
  var passesGroupGate2 = (input) => {
@@ -140926,8 +140874,8 @@ var makeTelegramApi = (input) => {
140926
140874
  },
140927
140875
  POLL_CALL_TIMEOUT_MS
140928
140876
  ),
140929
- sendMessage: async (chatId, text3) => {
140930
- for (const chunk of splitForTelegram(text3)) {
140877
+ sendMessage: async (chatId, text4) => {
140878
+ for (const chunk of splitForTelegram(text4)) {
140931
140879
  await call("sendMessage", { ...target(chatId), text: chunk });
140932
140880
  }
140933
140881
  },
@@ -140935,7 +140883,7 @@ var makeTelegramApi = (input) => {
140935
140883
  * 发一条消息,回它的 id。调用方保证 `text` 不超过单条上限(边写边更新的回复要自己
140936
140884
  * 在上限处翻篇,这里不替它切)。带 `rows` 就挂一块内联键盘。
140937
140885
  */
140938
- sendOne: (chatId, text3, rows) => sendSingle("sendMessage", chatId, { text: text3 }, rows),
140886
+ sendOne: (chatId, text4, rows) => sendSingle("sendMessage", chatId, { text: text4 }, rows),
140939
140887
  /**
140940
140888
  * 发一条富文本,回它的 id。`markdown` 已是平台要的样子。带 `rows` 就挂一块内联键盘。
140941
140889
  * 调用方保证不超富文本单条上限(这里不替它切)。
@@ -140945,23 +140893,23 @@ var makeTelegramApi = (input) => {
140945
140893
  * 改一条已发出的消息。内容没变(`message is not modified`)当成功。`rows` 不给就是
140946
140894
  * 去掉按钮:改了文字又要保留按钮的调用方得自己再传一次。
140947
140895
  */
140948
- editMessage: (chatId, messageId, text3, rows = []) => editSingle(chatId, messageId, { text: text3 }, rows),
140896
+ editMessage: (chatId, messageId, text4, rows = []) => editSingle(chatId, messageId, { text: text4 }, rows),
140949
140897
  /**
140950
140898
  * 把一条已发出的消息改成富文本。不带 `text`,只带 `rich_message`。内容没变
140951
140899
  * (`message is not modified`)当成功。`rows` 不给就是去掉按钮。
140952
140900
  */
140953
140901
  editRich: (chatId, messageId, markdown, rows = []) => editSingle(chatId, messageId, { rich_message: { markdown } }, rows),
140954
140902
  /** 带按钮的审批消息,一行一个按钮;回消息 id,之后才改得了它(平台没给就是 null)。 */
140955
- sendButtons: (chatId, text3, buttons) => sendSingle(
140903
+ sendButtons: (chatId, text4, buttons) => sendSingle(
140956
140904
  "sendMessage",
140957
140905
  chatId,
140958
- { text: text3 },
140906
+ { text: text4 },
140959
140907
  buttons.map((button) => [{ text: button.label, data: button.token }])
140960
140908
  ),
140961
140909
  /** 答完点击,不然客户端上那个按钮一直转圈。带 `text` 时点击者会看到一句提示。 */
140962
- answerCallback: (callbackQueryId, text3) => call("answerCallbackQuery", {
140910
+ answerCallback: (callbackQueryId, text4) => call("answerCallbackQuery", {
140963
140911
  callback_query_id: callbackQueryId,
140964
- ...text3 === void 0 ? {} : { text: text3 }
140912
+ ...text4 === void 0 ? {} : { text: text4 }
140965
140913
  }),
140966
140914
  sendPhoto: (chatId, photo) => upload("sendPhoto", "photo", chatId, photo),
140967
140915
  /** 以文件形式发(不压缩、不限尺寸比例):什么类型都行,音频与视频也走这条。 */
@@ -141071,9 +141019,9 @@ var toTelegramRichMarkdown = (value2) => {
141071
141019
 
141072
141020
  // src/plainTurnText.ts
141073
141021
  var RUNNING_LABEL_MAX_CHARS = 200;
141074
- var clip3 = (text3, max) => {
141075
- const chars = Array.from(text3);
141076
- return chars.length <= max ? text3 : `${chars.slice(0, max - 1).join("")}\u2026`;
141022
+ var clip3 = (text4, max) => {
141023
+ const chars = Array.from(text4);
141024
+ return chars.length <= max ? text4 : `${chars.slice(0, max - 1).join("")}\u2026`;
141077
141025
  };
141078
141026
  var turnTextParts = (view, t) => {
141079
141027
  const names = view.steps.map((kind) => t(`card.step.${kind}`));
@@ -141100,8 +141048,8 @@ var makeTurnWriter = (deps) => {
141100
141048
  let liveText = null;
141101
141049
  let frozen = 0;
141102
141050
  let consumed = 0;
141103
- const put = async (text3) => {
141104
- const bounded = text3.length <= deps.limit ? text3 : text3.slice(0, deps.limit);
141051
+ const put = async (text4) => {
141052
+ const bounded = text4.length <= deps.limit ? text4 : text4.slice(0, deps.limit);
141105
141053
  if (live === null) {
141106
141054
  const id = await deps.messages.send(bounded);
141107
141055
  if (id === null) throw new Error("telegram sent a message without an id");
@@ -141243,18 +141191,18 @@ var makeTelegramAdapter = (deps) => {
141243
141191
  limit: TELEGRAM_TEXT_MAX_CHARS,
141244
141192
  ...resume === void 0 ? {} : { resume },
141245
141193
  messages: {
141246
- send: (text3) => withRichFallback(
141247
- toTelegramRichMarkdown(text3),
141194
+ send: (text4) => withRichFallback(
141195
+ toTelegramRichMarkdown(text4),
141248
141196
  async (markdown) => (await apiFor(slot.binding)).sendRichOne(chatId, markdown),
141249
- async () => (await apiFor(slot.binding)).sendOne(chatId, text3)
141197
+ async () => (await apiFor(slot.binding)).sendOne(chatId, text4)
141250
141198
  ),
141251
- edit: (messageId, text3) => withRichFallback(
141252
- toTelegramRichMarkdown(text3),
141199
+ edit: (messageId, text4) => withRichFallback(
141200
+ toTelegramRichMarkdown(text4),
141253
141201
  async (markdown) => {
141254
141202
  await (await apiFor(slot.binding)).editRich(chatId, messageId, markdown);
141255
141203
  },
141256
141204
  async () => {
141257
- await (await apiFor(slot.binding)).editMessage(chatId, messageId, text3);
141205
+ await (await apiFor(slot.binding)).editMessage(chatId, messageId, text4);
141258
141206
  }
141259
141207
  )
141260
141208
  }
@@ -141326,17 +141274,17 @@ var makeTelegramAdapter = (deps) => {
141326
141274
  continue;
141327
141275
  }
141328
141276
  const resource = resourceOf2(message);
141329
- const text3 = commandForBot(
141277
+ const text4 = commandForBot(
141330
141278
  (message.text ?? message.caption ?? "").trim(),
141331
141279
  botUsername
141332
141280
  );
141333
- if (text3 === null) {
141281
+ if (text4 === null) {
141334
141282
  offset = nextOffset([update], offset);
141335
141283
  continue;
141336
141284
  }
141337
141285
  const gated = !passesGroupGate2({
141338
141286
  message,
141339
- text: text3,
141287
+ text: text4,
141340
141288
  hasResource: resource !== null,
141341
141289
  botUsername: botUsername ?? null,
141342
141290
  groupMention: binding.groupMention
@@ -141353,7 +141301,7 @@ var makeTelegramAdapter = (deps) => {
141353
141301
  offset = nextOffset([update], offset);
141354
141302
  const senderId = message.from === void 0 ? null : String(message.from.id);
141355
141303
  const chatKind = message.chat.type === "private" ? "private" : "group";
141356
- if (text3 === "" && resource === null) {
141304
+ if (text4 === "" && resource === null) {
141357
141305
  const unsupported = unsupportedTypeOf(message);
141358
141306
  if (unsupported === null) continue;
141359
141307
  handlers.onMessage({
@@ -141373,7 +141321,7 @@ var makeTelegramAdapter = (deps) => {
141373
141321
  chatId: chatIdOf(message),
141374
141322
  ...parentChatId === void 0 ? {} : { parentChatId },
141375
141323
  senderId,
141376
- text: text3,
141324
+ text: text4,
141377
141325
  chatKind,
141378
141326
  resources: resource === null ? [] : [
141379
141327
  {
@@ -141405,9 +141353,9 @@ var makeTelegramAdapter = (deps) => {
141405
141353
  }
141406
141354
  };
141407
141355
  },
141408
- sendText: async (binding, text3) => {
141356
+ sendText: async (binding, text4) => {
141409
141357
  const api = await apiFor(binding);
141410
- await api.sendMessage(binding.chatId, text3);
141358
+ await api.sendMessage(binding.chatId, text4);
141411
141359
  },
141412
141360
  checkConnection: async (bot) => {
141413
141361
  const token = tokenOf(bot);
@@ -141592,7 +141540,7 @@ ${line}`
141592
141540
  // src/turns.ts
141593
141541
  import { projectOrNull as projectOrNull2, threadOrNull as threadOrNull7 } from "@ycodium-ai/plugin-api";
141594
141542
  var TITLE_MAX_CHARS = 72;
141595
- var titleFrom = (text3) => text3.replace(/\s+/g, " ").slice(0, TITLE_MAX_CHARS) || "Chat thread";
141543
+ var titleFrom = (text4) => text4.replace(/\s+/g, " ").slice(0, TITLE_MAX_CHARS) || "Chat thread";
141596
141544
  var makeTurns = (core, deps) => {
141597
141545
  const { host, t, commit, bindChat, deliver } = core;
141598
141546
  const { queueFlow, rememberThreadProject } = deps;
@@ -141665,8 +141613,8 @@ var makeTurns = (core, deps) => {
141665
141613
  };
141666
141614
  const startTurn = async (binding, message) => {
141667
141615
  const chatKey = chatKeyOf(binding);
141668
- const text3 = message.text;
141669
- const threadId = await ensureThread(binding, text3 || message.resources[0]?.name || "Chat");
141616
+ const text4 = message.text;
141617
+ const threadId = await ensureThread(binding, text4 || message.resources[0]?.name || "Chat");
141670
141618
  if (threadId === null) return null;
141671
141619
  const carried = waitingFor(chatKey, threadId);
141672
141620
  pendingByChat.delete(chatKey);
@@ -141698,21 +141646,21 @@ var makeTurns = (core, deps) => {
141698
141646
  }
141699
141647
  }
141700
141648
  try {
141701
- await host.commands.dispatch({
141702
- type: "thread.turn.start",
141703
- commandId: crypto.randomUUID(),
141649
+ await host.threads.turns.start({
141650
+ requestId: crypto.randomUUID(),
141704
141651
  threadId,
141705
141652
  message: {
141706
141653
  messageId: userMessageId,
141707
141654
  role: "user",
141708
- text: notes.length === 0 ? text3 : [text3, ...notes].join("\n"),
141709
- attachments
141655
+ text: notes.length === 0 ? text4 : [text4, ...notes].join("\n"),
141656
+ attachments: attachments.map(
141657
+ (attachment) => attachment.type === "image" ? { ...attachment, type: "image" } : { ...attachment, type: "file" }
141658
+ )
141710
141659
  },
141711
- titleSeed: titleFrom(text3 || attachments[0]?.name || "Chat"),
141660
+ titleSeed: titleFrom(text4 || attachments[0]?.name || "Chat"),
141712
141661
  runtimeMode: binding.runtimeMode,
141713
141662
  interactionMode: interactionModeOf(chatKey),
141714
- ...intentAction !== void 0 ? { intentAction } : {},
141715
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
141663
+ ...intentAction !== void 0 ? { intentAction } : {}
141716
141664
  });
141717
141665
  } catch (error) {
141718
141666
  if (carried !== void 0) pendingByChat.set(chatKey, carried);
@@ -141728,7 +141676,7 @@ var makeTurns = (core, deps) => {
141728
141676
  chatKey,
141729
141677
  threadId,
141730
141678
  userMessageId,
141731
- text3.trim() || attachments[0]?.name || message.resources[0]?.name || "",
141679
+ text4.trim() || attachments[0]?.name || message.resources[0]?.name || "",
141732
141680
  binding.reply
141733
141681
  );
141734
141682
  return threadId;
@@ -141988,7 +141936,7 @@ var registerSettingsRowActions = (ctx, adapters) => {
141988
141936
  };
141989
141937
 
141990
141938
  // src/settingsView.ts
141991
- var isRecord2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
141939
+ var isRecord3 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
141992
141940
  var hasStoredSecret = (row, key) => {
141993
141941
  const value2 = row[key];
141994
141942
  return typeof value2 === "string" && value2 !== "";
@@ -142006,10 +141954,10 @@ var targetTable = () => ({
142006
141954
  });
142007
141955
  var targetViews = (config2) => {
142008
141956
  const table2 = config2[DELIVERY_TARGETS_FIELD];
142009
- if (!isRecord2(table2)) return [];
141957
+ if (!isRecord3(table2)) return [];
142010
141958
  const columns = deliveryTargetColumns();
142011
141959
  return Object.entries(table2).flatMap(([rowId, raw]) => {
142012
- if (!isRecord2(raw)) return [];
141960
+ if (!isRecord3(raw)) return [];
142013
141961
  const issues = targetIssues(raw);
142014
141962
  const values = Object.fromEntries(
142015
141963
  columns.map((column) => [column.key, readString(raw, column.key)])
@@ -142021,9 +141969,9 @@ var buildSettingsView = (config2, adapters) => {
142021
141969
  const columns = buildBotColumns(adapters);
142022
141970
  const table2 = config2[BOTS_FIELD];
142023
141971
  const bots = [];
142024
- if (isRecord2(table2)) {
141972
+ if (isRecord3(table2)) {
142025
141973
  for (const [rowId, raw] of Object.entries(table2)) {
142026
- if (!isRecord2(raw)) continue;
141974
+ if (!isRecord3(raw)) continue;
142027
141975
  const platform = platformOf(raw);
142028
141976
  const values = {};
142029
141977
  const secrets = {};
@@ -142086,10 +142034,10 @@ var applyRowEdit = (config2, { field, columns }, edit) => {
142086
142034
  for (const key of clearSecrets) {
142087
142035
  if (!secretColumns.has(key)) return columnError("not-a-secret", key);
142088
142036
  }
142089
- const table2 = isRecord2(config2[field]) ? config2[field] : {};
142037
+ const table2 = isRecord3(config2[field]) ? config2[field] : {};
142090
142038
  const requested = edit.rowId;
142091
142039
  const current = requested === void 0 ? {} : Object.hasOwn(table2, requested) ? table2[requested] : void 0;
142092
- if (!isRecord2(current)) return { ok: false, code: "unknown-row" };
142040
+ if (!isRecord3(current)) return { ok: false, code: "unknown-row" };
142093
142041
  const rowId = requested ?? nextRowId(table2);
142094
142042
  const nextRow = { ...current, ...edit.values };
142095
142043
  const clearing = clearSecrets.filter((key) => !Object.hasOwn(secrets, key));
@@ -142107,7 +142055,7 @@ var applyBotEdit = (config2, adapters, edit) => applyRowEdit(config2, { field: B
142107
142055
  var applyTargetEdit = (config2, edit) => applyRowEdit(config2, targetTable(), edit);
142108
142056
  var removeRow = (config2, field, rowId) => {
142109
142057
  const table2 = config2[field];
142110
- if (!isRecord2(table2) || !Object.hasOwn(table2, rowId)) return null;
142058
+ if (!isRecord3(table2) || !Object.hasOwn(table2, rowId)) return null;
142111
142059
  const nextTable = { ...table2 };
142112
142060
  delete nextTable[rowId];
142113
142061
  return { ...config2, [field]: nextTable };
@@ -142316,12 +142264,12 @@ var makeWechatAdapter = (deps) => {
142316
142264
  });
142317
142265
  return null;
142318
142266
  },
142319
- answerByText: (_binding, text3, options) => answerByNumber(text3, options)
142267
+ answerByText: (_binding, text4, options) => answerByNumber(text4, options)
142320
142268
  };
142321
142269
  };
142322
142270
 
142323
142271
  // src/wecomUpload.ts
142324
- import * as NodeCrypto2 from "node:crypto";
142272
+ import * as NodeCrypto3 from "node:crypto";
142325
142273
  var WECOM_CHUNK_BYTES = 512 * 1024;
142326
142274
  var WECOM_MAX_CHUNKS = 100;
142327
142275
  var WECOM_MIN_UPLOAD_BYTES = 5;
@@ -142354,7 +142302,7 @@ var uploadWecomMedia = async (input) => {
142354
142302
  filename: clampName(input.filename),
142355
142303
  total_size: bytes.byteLength,
142356
142304
  total_chunks: totalChunks,
142357
- md5: NodeCrypto2.createHash("md5").update(bytes).digest("hex")
142305
+ md5: NodeCrypto3.createHash("md5").update(bytes).digest("hex")
142358
142306
  });
142359
142307
  const uploadId = init.upload_id;
142360
142308
  if (typeof uploadId !== "string" || uploadId === "") {
@@ -142426,21 +142374,21 @@ var parseWecomMessage = (frame, botId) => {
142426
142374
  const ownIds = [...new Set([body.aibotid, botId].filter((id) => Boolean(id)))];
142427
142375
  const stripOwn = (value2) => ownIds.reduce((rest, id) => rest.replaceAll(`@${id}`, ""), value2);
142428
142376
  let mentionSource = "";
142429
- let text3 = "";
142377
+ let text4 = "";
142430
142378
  const resources = [];
142431
142379
  switch (body.msgtype) {
142432
142380
  case "text": {
142433
142381
  const raw = body.text?.content;
142434
142382
  if (typeof raw !== "string") return null;
142435
142383
  mentionSource = raw;
142436
- text3 = stripOwn(raw).trim();
142384
+ text4 = stripOwn(raw).trim();
142437
142385
  break;
142438
142386
  }
142439
142387
  case "voice": {
142440
142388
  const transcript = body.voice?.content;
142441
142389
  if (typeof transcript !== "string" || transcript.trim() === "") return null;
142442
142390
  mentionSource = transcript;
142443
- text3 = stripOwn(transcript).trim();
142391
+ text4 = stripOwn(transcript).trim();
142444
142392
  break;
142445
142393
  }
142446
142394
  case "image":
@@ -142474,7 +142422,7 @@ var parseWecomMessage = (frame, botId) => {
142474
142422
  }
142475
142423
  }
142476
142424
  if (parts.length === 0) return null;
142477
- text3 = parts.join("\n");
142425
+ text4 = parts.join("\n");
142478
142426
  break;
142479
142427
  }
142480
142428
  default:
@@ -142486,14 +142434,14 @@ var parseWecomMessage = (frame, botId) => {
142486
142434
  messageId,
142487
142435
  chatId,
142488
142436
  senderUserId: body.from?.userid ?? null,
142489
- text: text3,
142437
+ text: text4,
142490
142438
  resources,
142491
142439
  requestId: frame.headers?.req_id ?? null,
142492
142440
  chatType: mentioned ? "single" : chatType,
142493
142441
  conversation: chatType === "group" ? "group" : "single"
142494
142442
  };
142495
142443
  };
142496
- var splitForWecom = (text3, limit = WECOM_TEXT_MAX_CHARS) => splitMessage(text3, limit);
142444
+ var splitForWecom = (text4, limit = WECOM_TEXT_MAX_CHARS) => splitMessage(text4, limit);
142497
142445
  var decoder = new TextDecoder();
142498
142446
  var runWecomClient = (input) => {
142499
142447
  let sequence = 0;
@@ -142595,8 +142543,8 @@ var runWecomClient = (input) => {
142595
142543
  return false;
142596
142544
  }
142597
142545
  );
142598
- const sendText = async (chatId, text3) => {
142599
- for (const [index, content] of splitForWecom(text3).entries()) {
142546
+ const sendText = async (chatId, text4) => {
142547
+ for (const [index, content] of splitForWecom(text4).entries()) {
142600
142548
  const inboundRequestId = index === 0 ? pendingRequests.get(chatId) : void 0;
142601
142549
  if (inboundRequestId !== void 0) {
142602
142550
  pendingRequests.delete(chatId);
@@ -142726,7 +142674,7 @@ var runWecomClient = (input) => {
142726
142674
  };
142727
142675
 
142728
142676
  // src/wecomMedia.ts
142729
- import * as NodeCrypto3 from "node:crypto";
142677
+ import * as NodeCrypto4 from "node:crypto";
142730
142678
 
142731
142679
  // src/wecomPadding.ts
142732
142680
  var PADDING_BLOCK = 32;
@@ -142757,7 +142705,7 @@ var decryptWecomMedia = (cipher, aesKey) => {
142757
142705
  if (cipher.byteLength === 0 || cipher.byteLength % AES_BLOCK !== 0) {
142758
142706
  throw new WecomDecryptError("the ciphertext is not a whole number of blocks");
142759
142707
  }
142760
- const decipher = NodeCrypto3.createDecipheriv("aes-256-cbc", key, key.subarray(0, IV_BYTES));
142708
+ const decipher = NodeCrypto4.createDecipheriv("aes-256-cbc", key, key.subarray(0, IV_BYTES));
142761
142709
  decipher.setAutoPadding(false);
142762
142710
  const plain = Buffer.concat([decipher.update(cipher), decipher.final()]);
142763
142711
  const unpadded = stripPadding(plain);
@@ -142957,12 +142905,12 @@ ${kept}`;
142957
142905
  }
142958
142906
  };
142959
142907
  },
142960
- sendText: async (binding, text3) => {
142908
+ sendText: async (binding, text4) => {
142961
142909
  const client = clients.get(binding.rowId);
142962
142910
  if (client === void 0) {
142963
142911
  throw new ImNotConnectedError(`wecom bot '${binding.displayName}' has no connection.`);
142964
142912
  }
142965
- await client.sendText(binding.chatId, text3);
142913
+ await client.sendText(binding.chatId, text4);
142966
142914
  },
142967
142915
  checkConnection: async (bot) => {
142968
142916
  const { botId, botSecret, endpoint } = credentials2(bot);
@@ -143009,7 +142957,7 @@ ${kept}`;
143009
142957
  // 图 10 MB(只认 png / jpg / jpeg / gif)、文件 20 MB,来自企微官方文档「智能机器人长连接」。
143010
142958
  outboundLimits: { imageBytes: 10 * 1024 * 1024, fileBytes: 20 * 1024 * 1024, minBytes: 5 },
143011
142959
  imageMimeTypes: /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif"]),
143012
- answerByText: (_binding, text3, options) => answerByNumber(text3, options),
142960
+ answerByText: (_binding, text4, options) => answerByNumber(text4, options),
143013
142961
  fetchResource: async (binding, input) => {
143014
142962
  const parsed = JSON.parse(input.resource.key);
143015
142963
  const media = await fetchWecomMedia({
@@ -143062,8 +143010,8 @@ var normalizeApiBaseUrl = (value2) => {
143062
143010
  return raw.replace(/\/+$/u, "");
143063
143011
  };
143064
143012
  var byteLength = (value2) => Buffer.byteLength(value2, "utf8");
143065
- var splitUtf8ByBytes = (text3, maxBytes = WECOM_APP_TEXT_MAX_BYTES) => {
143066
- const value2 = typeof text3 === "string" ? text3 : "";
143013
+ var splitUtf8ByBytes = (text4, maxBytes = WECOM_APP_TEXT_MAX_BYTES) => {
143014
+ const value2 = typeof text4 === "string" ? text4 : "";
143067
143015
  if (value2 === "") return [""];
143068
143016
  const chunks = [];
143069
143017
  let current = "";
@@ -143279,7 +143227,7 @@ var WecomAppApi = class {
143279
143227
  import * as NodeHttp2 from "node:http";
143280
143228
 
143281
143229
  // src/wecomAppCrypto.ts
143282
- import * as NodeCrypto4 from "node:crypto";
143230
+ import * as NodeCrypto5 from "node:crypto";
143283
143231
  var AES_KEY_BYTES = 32;
143284
143232
  var RANDOM_BYTES = 16;
143285
143233
  var WecomAppCryptoError = class extends Error {
@@ -143302,13 +143250,13 @@ var timingSafeEqualString2 = (a, b) => {
143302
143250
  const left = Buffer.from(a);
143303
143251
  const right = Buffer.from(b);
143304
143252
  if (left.length === 0 || left.length !== right.length) return false;
143305
- return NodeCrypto4.timingSafeEqual(left, right);
143253
+ return NodeCrypto5.timingSafeEqual(left, right);
143306
143254
  };
143307
- var computeSignature = (token, timestamp, nonce, encrypt) => NodeCrypto4.createHash("sha1").update([token, timestamp, nonce, encrypt].sort().join("")).digest("hex");
143255
+ var computeSignature = (token, timestamp, nonce, encrypt) => NodeCrypto5.createHash("sha1").update([token, timestamp, nonce, encrypt].sort().join("")).digest("hex");
143308
143256
  var verifySignature = (token, timestamp, nonce, encrypt, signature) => timingSafeEqualString2(computeSignature(token, timestamp, nonce, encrypt), signature);
143309
143257
  var decrypt = (encodingAESKey, encryptText, expectReceiveId) => {
143310
143258
  const { key, iv } = parseEncodingAESKey(encodingAESKey);
143311
- const decipher = NodeCrypto4.createDecipheriv("aes-256-cbc", key, iv);
143259
+ const decipher = NodeCrypto5.createDecipheriv("aes-256-cbc", key, iv);
143312
143260
  decipher.setAutoPadding(false);
143313
143261
  let deciphered;
143314
143262
  try {
@@ -143367,10 +143315,10 @@ var createWecomAppCrypto = (input) => {
143367
143315
  decrypt: (encryptText) => decrypt(encodingAESKey, encryptText, corpId).message
143368
143316
  };
143369
143317
  };
143370
- var deriveCallbackPathSecret = (token, encodingAESKey) => NodeCrypto4.createHash("sha256").update(`${token.trim()}:${encodingAESKey.trim()}`).digest("hex").slice(0, 24);
143318
+ var deriveCallbackPathSecret = (token, encodingAESKey) => NodeCrypto5.createHash("sha256").update(`${token.trim()}:${encodingAESKey.trim()}`).digest("hex").slice(0, 24);
143371
143319
 
143372
143320
  // src/wecomAppParse.ts
143373
- var isRecord3 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
143321
+ var isRecord4 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
143374
143322
  var isXmlFormat = (raw) => {
143375
143323
  const trimmed = raw.trim();
143376
143324
  return trimmed.startsWith("<") && trimmed.endsWith(">");
@@ -143416,7 +143364,7 @@ var parseWecomAppPlainMessage = (raw) => {
143416
143364
  } catch {
143417
143365
  return null;
143418
143366
  }
143419
- if (!isRecord3(data)) return null;
143367
+ if (!isRecord4(data)) return null;
143420
143368
  const fromRaw = data["from"];
143421
143369
  const textRaw = data["text"];
143422
143370
  const imageRaw = data["image"];
@@ -143425,10 +143373,10 @@ var parseWecomAppPlainMessage = (raw) => {
143425
143373
  msgtype: String(data["msgtype"] ?? data["MsgType"] ?? "").toLowerCase(),
143426
143374
  createTime: data["createTime"] !== void 0 ? String(data["createTime"]) : data["CreateTime"] !== void 0 ? String(data["CreateTime"]) : void 0,
143427
143375
  agentId: data["agentid"] !== void 0 ? String(data["agentid"]) : data["AgentID"] !== void 0 ? String(data["AgentID"]) : void 0,
143428
- from: isRecord3(fromRaw) ? { userid: typeof fromRaw["userid"] === "string" ? fromRaw["userid"] : void 0 } : typeof data["FromUserName"] === "string" ? { userid: data["FromUserName"] } : void 0,
143376
+ from: isRecord4(fromRaw) ? { userid: typeof fromRaw["userid"] === "string" ? fromRaw["userid"] : void 0 } : typeof data["FromUserName"] === "string" ? { userid: data["FromUserName"] } : void 0,
143429
143377
  to: typeof data["to"] === "string" ? data["to"] : void 0,
143430
- text: isRecord3(textRaw) ? { content: typeof textRaw["content"] === "string" ? textRaw["content"] : void 0 } : void 0,
143431
- image: isRecord3(imageRaw) ? { url: typeof imageRaw["url"] === "string" ? imageRaw["url"] : void 0 } : void 0,
143378
+ text: isRecord4(textRaw) ? { content: typeof textRaw["content"] === "string" ? textRaw["content"] : void 0 } : void 0,
143379
+ image: isRecord4(imageRaw) ? { url: typeof imageRaw["url"] === "string" ? imageRaw["url"] : void 0 } : void 0,
143432
143380
  mediaId: typeof data["mediaid"] === "string" ? data["mediaid"] : void 0,
143433
143381
  recognition: typeof data["recognition"] === "string" ? data["recognition"] : void 0,
143434
143382
  event: String(data["event"] ?? data["eventtype"] ?? "").toLowerCase() || void 0,
@@ -143442,9 +143390,9 @@ var WECOM_APP_DEFAULT_CALLBACK_HOST = "127.0.0.1";
143442
143390
  var WECOM_APP_DEFAULT_CALLBACK_PORT = 30987;
143443
143391
  var WECOM_APP_CALLBACK_PATH_PREFIX = "/wecom-app-callback";
143444
143392
  var MAX_BODY_BYTES2 = 1 * 1024 * 1024;
143445
- var writeText = (res, status, text3, headers = {}) => {
143393
+ var writeText = (res, status, text4, headers = {}) => {
143446
143394
  if (res.writableEnded || res.destroyed) return;
143447
- const body = text3;
143395
+ const body = text4;
143448
143396
  res.writeHead(status, {
143449
143397
  "content-type": "text/plain; charset=utf-8",
143450
143398
  "content-length": Buffer.byteLength(body),
@@ -143972,11 +143920,11 @@ var makeWecomAppAdapter = (deps) => {
143972
143920
  }
143973
143921
  };
143974
143922
  },
143975
- sendText: async (binding, text3, options) => {
143923
+ sendText: async (binding, text4, options) => {
143976
143924
  if (options?.targetKind === "group") {
143977
143925
  throw new Error("wecom-app can only deliver to a user; group targets are not supported.");
143978
143926
  }
143979
- await apiFor(binding).sendText({ userId: binding.chatId, content: text3 });
143927
+ await apiFor(binding).sendText({ userId: binding.chatId, content: text4 });
143980
143928
  },
143981
143929
  sendImage: (binding, image2) => sendMedia(binding, "image", image2),
143982
143930
  sendFile: (binding, file) => sendMedia(binding, "file", file),
@@ -143993,14 +143941,14 @@ var makeWecomAppAdapter = (deps) => {
143993
143941
  await api.sendText({ userId: binding.chatId, content: numberedApprovalText(request) });
143994
143942
  return null;
143995
143943
  },
143996
- answerByText: (_binding, text3, options) => answerByNumber(text3, options)
143944
+ answerByText: (_binding, text4, options) => answerByNumber(text4, options)
143997
143945
  };
143998
143946
  };
143999
143947
 
144000
143948
  // src/index.ts
144001
143949
  var imPlugin = definePlugin({
144002
143950
  id: "im",
144003
- apiVersion: 9,
143951
+ apiVersion: 11,
144004
143952
  activate: async (ctx) => {
144005
143953
  const { t, setLanguage } = makeLiveTranslate(
144006
143954
  parseReplyLanguage(ctx.config[REPLY_LANGUAGE_FIELD])
@@ -144087,7 +144035,7 @@ var imPlugin = definePlugin({
144087
144035
  const failures = makeFailureNotices(core);
144088
144036
  const replyAnchors = makeReplyAnchors(core.host);
144089
144037
  const replyCards = makeReplyCards(core, failures, replyAnchors);
144090
- const teams = makeTeamRuns(core, { clearWorking: acknowledgements.clearWorking });
144038
+ const teams = makeTeamGoals(core);
144091
144039
  const notifications = makeNotifications(core, {
144092
144040
  clearWorking: acknowledgements.clearWorking,
144093
144041
  replyCards,
@@ -144116,10 +144064,9 @@ var imPlugin = definePlugin({
144116
144064
  const panelWiring = makePanelWiring(core, {
144117
144065
  enqueueForChat: chatQueue.enqueueForChat,
144118
144066
  sessions,
144119
- teams,
144120
144067
  modelPlan,
144121
144068
  rows: projectRows,
144122
- handleCommand: (binding, text3, teamChoices) => commands.handleCommand(binding, text3, teamChoices)
144069
+ handleCommand: (binding, text4) => commands.handleCommand(binding, text4)
144123
144070
  });
144124
144071
  const chatSetup = makeChatSetup(core, {
144125
144072
  rows: projectRows,
@@ -144131,6 +144078,7 @@ var imPlugin = definePlugin({
144131
144078
  sessions,
144132
144079
  modelPlan,
144133
144080
  chatSetup,
144081
+ teams,
144134
144082
  openPanel: (chatKey, reply) => panelWiring.panel.open(chatKey, reply)
144135
144083
  });
144136
144084
  const inbound = makeInbound(core, {