@ycodium-ai/plugin-im 0.2.3054 → 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))];
@@ -129055,9 +129024,9 @@ var makeQuestionFlow = (host) => {
129055
129024
  );
129056
129025
  return handledWith(null);
129057
129026
  };
129058
- const answerByText = async (chatKey, threadId, text3) => {
129027
+ const answerByText = async (chatKey, threadId, text4) => {
129059
129028
  const record2 = openQuestionOf(host.state(), chatKey, threadId);
129060
- const trimmed = text3.trim();
129029
+ const trimmed = text4.trim();
129061
129030
  if (record2 === void 0 || trimmed === "") return false;
129062
129031
  const unanswered = record2.items.filter(isUnanswered);
129063
129032
  const first = unanswered[0];
@@ -129185,7 +129154,7 @@ var makeQueueFlow = (host, deps) => {
129185
129154
  queuePaused: execution.queuePaused,
129186
129155
  intent: execution.intents.find((intent) => intent.intentId === intentId)
129187
129156
  });
129188
- const noteQueued = async (chatKey, threadId, messageId, text3, reply) => {
129157
+ const noteQueued = async (chatKey, threadId, messageId, text4, reply) => {
129189
129158
  const target2 = host.target(chatKey);
129190
129159
  if (target2 === void 0) return;
129191
129160
  let execution;
@@ -129211,7 +129180,7 @@ var makeQueueFlow = (host, deps) => {
129211
129180
  chatKey,
129212
129181
  threadId,
129213
129182
  intentId,
129214
- text: text3,
129183
+ text: text4,
129215
129184
  steerToken: host.newToken(),
129216
129185
  withdrawToken: host.newToken(),
129217
129186
  resumeToken: host.newToken()
@@ -129406,9 +129375,9 @@ var makeInteractions = (core, deps) => {
129406
129375
  },
129407
129376
  respondToUserInput: (input) => host.threads.userInput.respond(input),
129408
129377
  dispatch: (command) => host.commands.dispatch(command),
129409
- say: async (chatKey, text3) => {
129378
+ say: async (chatKey, text4) => {
129410
129379
  const binding = bindingForChatKey(chatKey);
129411
- if (binding !== void 0) await deliver(binding, text3);
129380
+ if (binding !== void 0) await deliver(binding, text4);
129412
129381
  },
129413
129382
  newToken: () => crypto.randomUUID().slice(0, 8),
129414
129383
  newId: () => crypto.randomUUID(),
@@ -129709,7 +129678,7 @@ var makeSettingsUpdater = (settings) => {
129709
129678
  var OPEN_ID_PREFIX = "ou_";
129710
129679
  var LARK_PLATFORM = "lark";
129711
129680
  var asRecord = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? { ...value2 } : {};
129712
- var text = (row, key) => {
129681
+ var text2 = (row, key) => {
129713
129682
  const value2 = row[key];
129714
129683
  return typeof value2 === "string" ? value2.trim() : "";
129715
129684
  };
@@ -129727,16 +129696,16 @@ var upsertLarkBot = (current, result) => {
129727
129696
  const sender = senderIdOf(result.creatorId);
129728
129697
  const existingId = Object.keys(table2).find((rowId2) => {
129729
129698
  const row2 = asRecord(table2[rowId2]);
129730
- const platform = text(row2, "platform") || DEFAULT_PLATFORM;
129731
- 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;
129732
129701
  });
129733
129702
  const rowId = existingId ?? freeRowId(table2);
129734
129703
  const base2 = existingId === void 0 ? {} : asRecord(table2[existingId]);
129735
- const keptList = text(base2, "allowedSenders");
129704
+ const keptList = text2(base2, "allowedSenders");
129736
129705
  const allowedSenders = keptList !== "" ? keptList : sender ?? "";
129737
129706
  const row = {
129738
129707
  ...base2,
129739
- displayName: text(base2, "displayName") || result.appName,
129708
+ displayName: text2(base2, "displayName") || result.appName,
129740
129709
  platform: LARK_PLATFORM,
129741
129710
  larkAppId: result.appId,
129742
129711
  larkAppSecret: result.appSecret,
@@ -130211,10 +130180,10 @@ var openConsole = async (deps, jar) => {
130211
130180
  ...body === void 0 ? {} : { body },
130212
130181
  signal
130213
130182
  });
130214
- const text3 = await response.text();
130183
+ const text4 = await response.text();
130215
130184
  let data = null;
130216
130185
  try {
130217
- data = JSON.parse(text3);
130186
+ data = JSON.parse(text4);
130218
130187
  } catch {
130219
130188
  data = null;
130220
130189
  }
@@ -130438,8 +130407,8 @@ var TOKEN_LIKE = /[A-Za-z0-9_=-]{24,}/g;
130438
130407
  var MIN_SECRET_LENGTH = 6;
130439
130408
  var makeRedactor = () => {
130440
130409
  const secrets = /* @__PURE__ */ new Set();
130441
- const redact = (text3) => {
130442
- let out = text3;
130410
+ const redact = (text4) => {
130411
+ let out = text4;
130443
130412
  for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {
130444
130413
  out = out.split(secret).join(MASK);
130445
130414
  }
@@ -130450,7 +130419,7 @@ var makeRedactor = () => {
130450
130419
  if (typeof secret === "string" && secret.length >= MIN_SECRET_LENGTH) secrets.add(secret);
130451
130420
  },
130452
130421
  redact,
130453
- detail: (text3) => redact(text3).slice(0, DETAIL_MAX_CHARS)
130422
+ detail: (text4) => redact(text4).slice(0, DETAIL_MAX_CHARS)
130454
130423
  };
130455
130424
  };
130456
130425
 
@@ -131278,10 +131247,10 @@ var registerLarkSetup = (ctx, options = {}) => {
131278
131247
  };
131279
131248
 
131280
131249
  // src/splitMessage.ts
131281
- var splitMessage = (text3, limit) => {
131282
- if (text3.length <= limit) return [text3];
131250
+ var splitMessage = (text4, limit) => {
131251
+ if (text4.length <= limit) return [text4];
131283
131252
  const chunks = [];
131284
- let rest = text3;
131253
+ let rest = text4;
131285
131254
  while (rest.length > limit) {
131286
131255
  const window2 = rest.slice(0, limit);
131287
131256
  const paragraph2 = window2.lastIndexOf("\n\n");
@@ -131499,7 +131468,7 @@ var createChat = async (input) => {
131499
131468
  }
131500
131469
  return chatId;
131501
131470
  };
131502
- var splitForLark = (text3) => splitMessage(text3, LARK_TEXT_MAX_CHARS);
131471
+ var splitForLark = (text4) => splitMessage(text4, LARK_TEXT_MAX_CHARS);
131503
131472
 
131504
131473
  // src/larkCardStream.ts
131505
131474
  var LARK_CARD_THROTTLE_MS = 400;
@@ -132541,10 +132510,10 @@ var REBuilder = class {
132541
132510
  }
132542
132511
  };
132543
132512
  var web_schema = {
132544
- validate: (text3, pos, self2) => {
132513
+ validate: (text4, pos, self2) => {
132545
132514
  const re = self2.re.get_http_validator();
132546
132515
  re.lastIndex = pos;
132547
- const m = re.exec(text3);
132516
+ const m = re.exec(text4);
132548
132517
  return m ? m[0].length : 0;
132549
132518
  },
132550
132519
  normalize: (match, self2) => self2.normalize(match)
@@ -132554,13 +132523,13 @@ var defaultSchemas = {
132554
132523
  "https:": web_schema,
132555
132524
  "ftp:": web_schema,
132556
132525
  "//": {
132557
- validate: function(text3, pos, self2) {
132526
+ validate: function(text4, pos, self2) {
132558
132527
  const re = self2.re.get_relative_proto_validator();
132559
132528
  re.lastIndex = pos;
132560
- const m = re.exec(text3);
132529
+ const m = re.exec(text4);
132561
132530
  if (m) {
132562
- if (pos >= 3 && text3[pos - 3] === ":") return 0;
132563
- 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;
132564
132533
  return m[0].length;
132565
132534
  }
132566
132535
  return 0;
@@ -132568,10 +132537,10 @@ var defaultSchemas = {
132568
132537
  normalize: (match, self2) => self2.normalize(match)
132569
132538
  },
132570
132539
  "mailto:": {
132571
- validate: function(text3, pos, self2) {
132540
+ validate: function(text4, pos, self2) {
132572
132541
  const re = self2.re.get_mailto_validator();
132573
132542
  re.lastIndex = pos;
132574
- const m = re.exec(text3);
132543
+ const m = re.exec(text4);
132575
132544
  return m ? m[0].length : 0;
132576
132545
  },
132577
132546
  normalize: (match, self2) => self2.normalize(match)
@@ -132610,8 +132579,8 @@ var Match = class {
132610
132579
  text;
132611
132580
  /** Normalized URL of matched string. */
132612
132581
  url;
132613
- constructor(text3, schema, index, lastIndex) {
132614
- const raw = text3.slice(index, lastIndex);
132582
+ constructor(text4, schema, index, lastIndex) {
132583
+ const raw = text4.slice(index, lastIndex);
132615
132584
  this.schema = schema.toLowerCase();
132616
132585
  this.index = index;
132617
132586
  this.lastIndex = lastIndex;
@@ -132717,24 +132686,24 @@ var LinkifyIt = class {
132717
132686
  *
132718
132687
  * @param text Text to scan.
132719
132688
  */
132720
- test(text3) {
132721
- if (!text3.length) return false;
132689
+ test(text4) {
132690
+ if (!text4.length) return false;
132722
132691
  let m, re;
132723
132692
  re = this.re.get_schema_search();
132724
132693
  re.lastIndex = 0;
132725
- 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;
132726
132695
  if (this.__opts__.fuzzyLink && this.__schemas__["http:"]) {
132727
132696
  re = this.re.get_fuzzy_link_search();
132728
132697
  re.lastIndex = 0;
132729
- if (re.exec(text3) !== null) return true;
132698
+ if (re.exec(text4) !== null) return true;
132730
132699
  }
132731
132700
  if (this.__opts__.fuzzyEmail && this.__schemas__["mailto:"]) {
132732
- if (text3.indexOf("@") >= 0) {
132701
+ if (text4.indexOf("@") >= 0) {
132733
132702
  const mailHostRe = this.re.get_fuzzy_mail_host_search();
132734
132703
  const mailNameRe = this.re.get_mail_name_validator();
132735
132704
  mailHostRe.lastIndex = 0;
132736
- while ((m = mailHostRe.exec(text3)) !== null) {
132737
- 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);
132738
132707
  if (mailNameRe.test(name)) return true;
132739
132708
  }
132740
132709
  }
@@ -132749,9 +132718,9 @@ var LinkifyIt = class {
132749
132718
  * @param schema Rule (schema) name.
132750
132719
  * @param pos Text offset to check from.
132751
132720
  */
132752
- testSchemaAt(text3, schema, pos) {
132721
+ testSchemaAt(text4, schema, pos) {
132753
132722
  if (!this.__schemas__[schema.toLowerCase()]) return 0;
132754
- 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);
132755
132724
  }
132756
132725
  /**
132757
132726
  * Returns array of found link descriptions or `null` on fail. We strongly
@@ -132759,7 +132728,7 @@ var LinkifyIt = class {
132759
132728
  *
132760
132729
  * @param text Text to scan.
132761
132730
  */
132762
- match(text3) {
132731
+ match(text4) {
132763
132732
  const result = [];
132764
132733
  const schemaRe = this.re.get_schema_search();
132765
132734
  let fuzzyLinkRe;
@@ -132772,7 +132741,7 @@ var LinkifyIt = class {
132772
132741
  let fuzzyLinkDone = false;
132773
132742
  let fuzzyEmailDone = false;
132774
132743
  let pos = 0;
132775
- if (!text3.length) return null;
132744
+ if (!text4.length) return null;
132776
132745
  schemaRe.lastIndex = 0;
132777
132746
  if (this.__opts__.fuzzyLink && this.__schemas__["http:"]) {
132778
132747
  fuzzyLinkRe = this.re.get_fuzzy_link_search();
@@ -132788,13 +132757,13 @@ var LinkifyIt = class {
132788
132757
  if (mailHostRe && mailNameRe && !fuzzyEmailDone && (!fuzzyEmailCandidate || fuzzyEmailCandidate.index < pos)) {
132789
132758
  if (mailHostRe.lastIndex < scanFrom) mailHostRe.lastIndex = scanFrom;
132790
132759
  for (; ; ) {
132791
- const m = mailHostRe.exec(text3);
132760
+ const m = mailHostRe.exec(text4);
132792
132761
  if (!m) {
132793
132762
  fuzzyEmailDone = true;
132794
132763
  fuzzyEmailCandidate = void 0;
132795
132764
  break;
132796
132765
  }
132797
- 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));
132798
132767
  if (!name) continue;
132799
132768
  fuzzyEmailCandidate = {
132800
132769
  schema: "mailto:",
@@ -132808,7 +132777,7 @@ var LinkifyIt = class {
132808
132777
  if (fuzzyLinkRe && !fuzzyLinkDone && (!fuzzyLinkCandidate || fuzzyLinkCandidate.index < pos)) {
132809
132778
  if (fuzzyLinkRe.lastIndex < scanFrom) fuzzyLinkRe.lastIndex = scanFrom;
132810
132779
  for (; ; ) {
132811
- const m = fuzzyLinkRe.exec(text3);
132780
+ const m = fuzzyLinkRe.exec(text4);
132812
132781
  if (!m) {
132813
132782
  fuzzyLinkDone = true;
132814
132783
  fuzzyLinkCandidate = void 0;
@@ -132829,7 +132798,7 @@ var LinkifyIt = class {
132829
132798
  if (!schemaDone) for (; ; ) {
132830
132799
  if (!schemaPrefix) {
132831
132800
  if (schemaRe.lastIndex < scanFrom) schemaRe.lastIndex = scanFrom;
132832
- const m = schemaRe.exec(text3);
132801
+ const m = schemaRe.exec(text4);
132833
132802
  if (!m) {
132834
132803
  schemaDone = true;
132835
132804
  break;
@@ -132847,7 +132816,7 @@ var LinkifyIt = class {
132847
132816
  if (fuzzyCandidate && schemaPrefix.index > fuzzyCandidate.index) break;
132848
132817
  const prefix = schemaPrefix;
132849
132818
  schemaPrefix = void 0;
132850
- const len = this.testSchemaAt(text3, prefix.schema, prefix.lastIndex);
132819
+ const len = this.testSchemaAt(text4, prefix.schema, prefix.lastIndex);
132851
132820
  if (len) {
132852
132821
  schemaCandidate = {
132853
132822
  schema: prefix.schema,
@@ -132863,7 +132832,7 @@ var LinkifyIt = class {
132863
132832
  if (!candidate) break;
132864
132833
  if (candidate === fuzzyEmailCandidate) fuzzyEmailCandidate = void 0;
132865
132834
  else if (candidate === fuzzyLinkCandidate) fuzzyLinkCandidate = void 0;
132866
- const match = new Match(text3, candidate.schema, candidate.index, candidate.lastIndex);
132835
+ const match = new Match(text4, candidate.schema, candidate.index, candidate.lastIndex);
132867
132836
  if (match.schema) this.__schemas__[match.schema].normalize(match, this);
132868
132837
  else this.normalize(match);
132869
132838
  result.push(match);
@@ -132878,13 +132847,13 @@ var LinkifyIt = class {
132878
132847
  *
132879
132848
  * @param text Text to scan.
132880
132849
  */
132881
- matchAtStart(text3) {
132882
- if (!text3.length) return null;
132883
- 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);
132884
132853
  if (!m) return null;
132885
- const len = this.testSchemaAt(text3, m[2], m[0].length);
132854
+ const len = this.testSchemaAt(text4, m[2], m[0].length);
132886
132855
  if (!len) return null;
132887
- 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);
132888
132857
  this.__schemas__[match.schema].normalize(match, this);
132889
132858
  return match;
132890
132859
  }
@@ -133864,8 +133833,8 @@ function linkify$1(state) {
133864
133833
  }
133865
133834
  if (htmlLinkLevel > 0) continue;
133866
133835
  if (currentToken.type === "text" && state.md.linkify.test(currentToken.content)) {
133867
- const text3 = currentToken.content;
133868
- let links = state.md.linkify.match(text3);
133836
+ const text4 = currentToken.content;
133837
+ let links = state.md.linkify.match(text4);
133869
133838
  const nodes = [];
133870
133839
  let level = currentToken.level;
133871
133840
  let lastPos = 0;
@@ -133881,7 +133850,7 @@ function linkify$1(state) {
133881
133850
  const pos = links[ln].index;
133882
133851
  if (pos > lastPos) {
133883
133852
  const token = new state.Token("text", "", 0);
133884
- token.content = text3.slice(lastPos, pos);
133853
+ token.content = text4.slice(lastPos, pos);
133885
133854
  token.level = level;
133886
133855
  nodes.push(token);
133887
133856
  }
@@ -133902,9 +133871,9 @@ function linkify$1(state) {
133902
133871
  nodes.push(token_c);
133903
133872
  lastPos = links[ln].lastIndex;
133904
133873
  }
133905
- if (lastPos < text3.length) {
133874
+ if (lastPos < text4.length) {
133906
133875
  const token = new state.Token("text", "", 0);
133907
- token.content = text3.slice(lastPos);
133876
+ token.content = text4.slice(lastPos);
133908
133877
  token.level = level;
133909
133878
  nodes.push(token);
133910
133879
  }
@@ -134015,19 +133984,19 @@ function process_inlines(tokens, state) {
134015
133984
  for (j = stack.length - 1; j >= 0; j--) if (stack[j].level <= thisLevel) break;
134016
133985
  truncateStack(stack, heads, j + 1);
134017
133986
  if (token.type !== "text") continue;
134018
- const text3 = token.content;
133987
+ const text4 = token.content;
134019
133988
  let pos = 0;
134020
- const max = text3.length;
133989
+ const max = text4.length;
134021
133990
  OUTER: while (pos < max) {
134022
133991
  QUOTE_RE.lastIndex = pos;
134023
- const t = QUOTE_RE.exec(text3);
133992
+ const t = QUOTE_RE.exec(text4);
134024
133993
  if (!t) break;
134025
133994
  let canOpen = true;
134026
133995
  let canClose = true;
134027
133996
  pos = t.index + 1;
134028
133997
  const isSingle = t[0] === "'";
134029
133998
  let lastChar = 32;
134030
- if (t.index - 1 >= 0) lastChar = text3.charCodeAt(t.index - 1);
133999
+ if (t.index - 1 >= 0) lastChar = text4.charCodeAt(t.index - 1);
134031
134000
  else for (j = i - 1; j >= 0; j--) {
134032
134001
  if (tokens[j].type === "softbreak" || tokens[j].type === "hardbreak") break;
134033
134002
  if (!tokens[j].content) continue;
@@ -134035,7 +134004,7 @@ function process_inlines(tokens, state) {
134035
134004
  break;
134036
134005
  }
134037
134006
  let nextChar = 32;
134038
- if (pos < max) nextChar = text3.charCodeAt(pos);
134007
+ if (pos < max) nextChar = text4.charCodeAt(pos);
134039
134008
  else for (j = i + 1; j < tokens.length; j++) {
134040
134009
  if (tokens[j].type === "softbreak" || tokens[j].type === "hardbreak") break;
134041
134010
  if (!tokens[j].content) continue;
@@ -135370,7 +135339,7 @@ function isTerminatorChar(ch) {
135370
135339
  return false;
135371
135340
  }
135372
135341
  }
135373
- function text2(state, silent) {
135342
+ function text3(state, silent) {
135374
135343
  let pos = state.pos;
135375
135344
  while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) pos++;
135376
135345
  if (pos === state.pos) return false;
@@ -136044,7 +136013,7 @@ function fragments_join(state) {
136044
136013
  if (curr !== last) tokens.length = last;
136045
136014
  }
136046
136015
  var _rules = [
136047
- ["text", text2],
136016
+ ["text", text3],
136048
136017
  ["linkify", linkify],
136049
136018
  ["newline", newline],
136050
136019
  ["escape", escape2],
@@ -136680,8 +136649,8 @@ var markdownToElements = (input) => {
136680
136649
  const buffer = [];
136681
136650
  let tableCount = 0;
136682
136651
  const flushBuffer = () => {
136683
- const text3 = buffer.join("\n\n").replace(/\n{3,}/g, "\n\n").trim();
136684
- 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 });
136685
136654
  buffer.length = 0;
136686
136655
  };
136687
136656
  let index = 0;
@@ -136693,8 +136662,8 @@ var markdownToElements = (input) => {
136693
136662
  continue;
136694
136663
  }
136695
136664
  if (token.type === "heading_open") {
136696
- const text3 = (tokens[index + 1]?.content ?? "").replace(/^#{1,6}\s+/, "").trim();
136697
- if (text3 !== "") buffer.push(`**${text3}**`);
136665
+ const text4 = (tokens[index + 1]?.content ?? "").replace(/^#{1,6}\s+/, "").trim();
136666
+ if (text4 !== "") buffer.push(`**${text4}**`);
136698
136667
  index += 3;
136699
136668
  continue;
136700
136669
  }
@@ -136756,23 +136725,23 @@ var STATUS_TEMPLATE = {
136756
136725
  continued: "grey"
136757
136726
  };
136758
136727
  var encoder = new TextEncoder();
136759
- var stripAngleBrackets = (text3) => text3.replaceAll("<", "").replaceAll(">", "");
136760
- var truncateTail = (text3, t, maxBytes = MAX_CARD_BODY_BYTES) => {
136761
- 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;
136762
136731
  const marker = `${t("card.truncated", { count: 9999999 })}
136763
136732
  `;
136764
136733
  const budget = maxBytes - encoder.encode(marker).length;
136765
136734
  if (budget < 1) return "";
136766
136735
  const kept = [];
136767
136736
  let used = 0;
136768
- for (const char of Array.from(text3).toReversed()) {
136737
+ for (const char of Array.from(text4).toReversed()) {
136769
136738
  const size = encoder.encode(char).length;
136770
136739
  if (used + size > budget) break;
136771
136740
  used += size;
136772
136741
  kept.push(char);
136773
136742
  }
136774
136743
  const tail = kept.toReversed().join("");
136775
- const dropped = Array.from(text3).length - kept.length;
136744
+ const dropped = Array.from(text4).length - kept.length;
136776
136745
  return `${t("card.truncated", { count: dropped })}
136777
136746
  ${tail}`;
136778
136747
  };
@@ -136929,8 +136898,8 @@ var buildChoiceCard = (card) => {
136929
136898
  var import_node_sdk = __toESM(require_lib2(), 1);
136930
136899
 
136931
136900
  // src/larkPost.ts
136932
- var styledText = (text3, style) => {
136933
- let out = text3;
136901
+ var styledText = (text4, style) => {
136902
+ let out = text4;
136934
136903
  if (style?.includes("bold")) out = `**${out}**`;
136935
136904
  if (style?.includes("italic")) out = `*${out}*`;
136936
136905
  if (style?.includes("lineThrough")) out = `~~${out}~~`;
@@ -137014,18 +136983,18 @@ var serializePost = (content, botIds = /* @__PURE__ */ new Set()) => {
137014
136983
  placeholderByKey.set(key, placeholderOf(element, index));
137015
136984
  }
137016
136985
  }
137017
- const text4 = md2.replace(
136986
+ const text5 = md2.replace(
137018
136987
  /!\[(?:img|video|file)\]\(([^)]+)\)/g,
137019
136988
  (whole, rawKey) => placeholderByKey.get(rawKey.trim()) ?? whole
137020
136989
  );
137021
- return { text: text4, resources };
136990
+ return { text: text5, resources };
137022
136991
  }
137023
136992
  const paragraphs = (parsed.content ?? []).map(
137024
136993
  (row) => row.map((element) => serializeElement(element, indexOf.get(element) ?? null, botIds)).join("")
137025
136994
  );
137026
- const text3 = paragraphs.map((line) => line.trim()).filter((line) => line !== "").join("\n");
137027
- if (text3 === "" && resources.length === 0) return void 0;
137028
- 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 };
137029
136998
  };
137030
136999
 
137031
137000
  // src/larkInbound.ts
@@ -137098,8 +137067,8 @@ var readResource = (messageType, content) => {
137098
137067
  return null;
137099
137068
  };
137100
137069
  var readText = (content) => {
137101
- const text3 = readJson(content)?.["text"];
137102
- return typeof text3 === "string" ? text3 : null;
137070
+ const text4 = readJson(content)?.["text"];
137071
+ return typeof text4 === "string" ? text4 : null;
137103
137072
  };
137104
137073
  var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention = true) => {
137105
137074
  if (event.sender?.sender_type === "app") return null;
@@ -137134,9 +137103,9 @@ var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention
137134
137103
  const single = post === void 0 ? readResource(messageType, message.content) : null;
137135
137104
  const resources = post !== void 0 ? post.resources : single === null ? [] : [single];
137136
137105
  const raw = post !== void 0 ? post.text : messageType === "text" ? readText(message.content) : null;
137137
- const text3 = mentions.reduce((value2, mention) => value2.replaceAll(mention.key, ""), raw ?? "").trim();
137138
- if (text3.length === 0 && resources.length === 0) return null;
137139
- 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 };
137140
137109
  };
137141
137110
  var fetchMessageResource = async (input) => {
137142
137111
  const url = `${LARK_BASE}/im/v1/messages/${encodeURIComponent(
@@ -137494,10 +137463,10 @@ var makeLarkAdapter = (deps) => {
137494
137463
  name: input.name,
137495
137464
  memberOpenIds: input.memberIds
137496
137465
  }),
137497
- sendText: async (binding, text3, options) => {
137466
+ sendText: async (binding, text4, options) => {
137498
137467
  const target2 = await sendTarget(binding);
137499
137468
  const receiveIdType = options?.targetKind === "user" ? "open_id" : "chat_id";
137500
- for (const chunk of splitForLark(text3)) {
137469
+ for (const chunk of splitForLark(text4)) {
137501
137470
  const messageId = await sendChatText({
137502
137471
  ...target2,
137503
137472
  receiveIdType,
@@ -137853,7 +137822,6 @@ var en_default = {
137853
137822
  turnFailedNoDetail: "This turn didn't finish. Reference {{ref}}. Send the message again; if it keeps failing, send /new to start a new conversation.",
137854
137823
  turnFailedBrief: "This turn didn't finish: {{detail}}\nSend the message again; if it keeps failing, send /new to start a new conversation.",
137855
137824
  turnFailedBriefNoDetail: "This turn didn't finish. Send the message again; if it keeps failing, send /new to start a new conversation.",
137856
- teamGone: "The team this chat was sending to no longer exists, so messages go to a normal session again.",
137857
137825
  attachmentReceived: "Got {{names}} ({{count}} waiting). Tell me what to do with them.",
137858
137826
  attachmentFailed: "Could not take {{name}}: {{reason}}.",
137859
137827
  attachmentReason: {
@@ -137921,10 +137889,8 @@ var en_default = {
137921
137889
  plainNotice: "Queued: this message goes out when the current reply finishes."
137922
137890
  },
137923
137891
  command: {
137924
- 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.",
137925
137893
  threadSelected: "OK. From now on messages start a normal session.",
137926
- teamNotFound: 'No team is called "{{query}}", or more than one matches.',
137927
- noTeams: "There are no teams on this machine yet.",
137928
137894
  newSession: "OK. The next message starts a new session.",
137929
137895
  stopNoSession: "Nothing is running in this chat.",
137930
137896
  stopNoTurn: "No turn is running right now.",
@@ -137934,7 +137900,7 @@ var en_default = {
137934
137900
  stopped: "Stopped. The session is still there \u2014 just keep talking."
137935
137901
  },
137936
137902
  status: {
137937
- routedTeam: "Sent to: {{title}}",
137903
+ routedTeam: "Sent to: this project's team",
137938
137904
  routedThread: "Normal session",
137939
137905
  nothingRunning: "{{where}}. Nothing is running.",
137940
137906
  session: "Session: {{title}}",
@@ -137945,20 +137911,13 @@ var en_default = {
137945
137911
  project: "Project: {{title}}",
137946
137912
  noProject: "No project picked yet. Send /repo to pick one."
137947
137913
  },
137948
- targets: {
137949
- currentThread: "This chat is on a normal session.",
137950
- currentTeam: "Sent to: {{title}}",
137951
- noTeams: "There are no teams on this machine yet.",
137952
- teamList: "Teams you can pick:",
137953
- hint: "Use /team name to switch, /thread to go back to a normal session."
137954
- },
137955
137914
  help: {
137956
137915
  title: "Commands:",
137957
137916
  continue: "\xB7 /continue \u2014 resume sending after /stop or a failure paused it; the waiting messages go out",
137958
137917
  stop: "\xB7 /stop \u2014 stop the turn that is running; the session stays",
137959
137918
  status: "\xB7 /status \u2014 what is going on right now",
137960
137919
  new: "\xB7 /new \u2014 forget the current session; the next message starts a new one",
137961
- 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",
137962
137921
  thread: "\xB7 /thread \u2014 go back to a normal session",
137963
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.",
137964
137923
  sessions: "\xB7 /sessions \u2014 list the sessions this bot opened for this chat's project",
@@ -138082,11 +138041,6 @@ var en_default = {
138082
138041
  title: "Pick a session",
138083
138042
  hint: "Tap one to switch to it."
138084
138043
  },
138085
- teams: {
138086
- title: "Pick a team",
138087
- hint: "Tap a team and the next messages go to it.",
138088
- unavailable: "Could not read the team list."
138089
- },
138090
138044
  models: {
138091
138045
  title: "Pick a model"
138092
138046
  },
@@ -138257,7 +138211,7 @@ var en_default = {
138257
138211
  model: "See or switch the model",
138258
138212
  plan: "Toggle plan mode",
138259
138213
  repo: "Pick the project this chat works on",
138260
- team: "Send the next messages to a team",
138214
+ team: "Give this project's team a goal with each message",
138261
138215
  thread: "Go back to a normal session",
138262
138216
  panel: "Open the command panel",
138263
138217
  help: "Show all commands"
@@ -138321,6 +138275,14 @@ var en_default = {
138321
138275
  removeConfirm: "Delete this target",
138322
138276
  removeFailed: "Couldn't delete this target."
138323
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}}"
138324
138286
  }
138325
138287
  };
138326
138288
 
@@ -138524,7 +138486,6 @@ var zh_CN_default = {
138524
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",
138525
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",
138526
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",
138527
- 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",
138528
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",
138529
138490
  attachmentFailed: "\u6CA1\u80FD\u6536\u4E0B {{name}}\uFF1A{{reason}}\u3002",
138530
138491
  attachmentReason: {
@@ -138592,10 +138553,8 @@ var zh_CN_default = {
138592
138553
  plainNotice: "\u5DF2\u6392\u961F\uFF1A\u5F53\u524D\u8FD9\u4E00\u8F6E\u56DE\u590D\u7ED3\u675F\u540E\u53D1\u51FA\u3002"
138593
138554
  },
138594
138555
  command: {
138595
- 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",
138596
138557
  threadSelected: "\u597D\uFF0C\u63A5\u4E0B\u6765\u5F00\u666E\u901A\u4F1A\u8BDD\u3002",
138597
- teamNotFound: "\u6CA1\u627E\u5230\u53EB\u300C{{query}}\u300D\u7684\u961F\uFF0C\u4E5F\u53EF\u80FD\u662F\u4E0D\u6B62\u4E00\u652F\u5BF9\u5F97\u4E0A\u3002",
138598
- noTeams: "\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD8\u6CA1\u6709\u56E2\u961F\u3002",
138599
138558
  newSession: "\u597D\uFF0C\u4E0B\u4E00\u53E5\u8BDD\u5F00\u4E00\u6761\u65B0\u4F1A\u8BDD\u3002",
138600
138559
  stopNoSession: "\u8FD9\u4E2A\u804A\u5929\u73B0\u5728\u6CA1\u6709\u5728\u8DD1\u7684\u6D3B\u513F\u3002",
138601
138560
  stopNoTurn: "\u73B0\u5728\u6CA1\u6709\u5728\u8DD1\u7684\u4E00\u8F6E\u3002",
@@ -138605,7 +138564,7 @@ var zh_CN_default = {
138605
138564
  stopped: "\u505C\u4E86\u3002\u4F1A\u8BDD\u8FD8\u5728\uFF0C\u63A5\u7740\u8BF4\u5C31\u884C\u3002"
138606
138565
  },
138607
138566
  status: {
138608
- routedTeam: "\u6D3E\u7ED9\uFF1A{{title}}",
138567
+ routedTeam: "\u6D3E\u7ED9\uFF1A\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F",
138609
138568
  routedThread: "\u666E\u901A\u4F1A\u8BDD",
138610
138569
  nothingRunning: "{{where}}\u3002\u73B0\u5728\u6CA1\u6709\u5728\u8DD1\u7684\u6D3B\u513F\u3002",
138611
138570
  session: "\u4F1A\u8BDD\uFF1A{{title}}",
@@ -138616,20 +138575,13 @@ var zh_CN_default = {
138616
138575
  project: "\u9879\u76EE\uFF1A{{title}}",
138617
138576
  noProject: "\u8FD8\u6CA1\u9009\u9879\u76EE\u3002\u53D1 /repo \u9009\u4E00\u4E2A\u3002"
138618
138577
  },
138619
- targets: {
138620
- currentThread: "\u73B0\u5728\u8FD9\u4E2A\u804A\u5929\u5F00\u7684\u662F\u666E\u901A\u4F1A\u8BDD\u3002",
138621
- currentTeam: "\u73B0\u5728\u6D3E\u7ED9\uFF1A{{title}}",
138622
- noTeams: "\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD8\u6CA1\u6709\u56E2\u961F\u3002",
138623
- teamList: "\u53EF\u9009\u7684\u961F\uFF1A",
138624
- hint: "\u7528 /team \u961F\u540D \u5207\u6362\uFF0C/thread \u5207\u56DE\u666E\u901A\u4F1A\u8BDD\u3002"
138625
- },
138626
138578
  help: {
138627
138579
  title: "\u80FD\u7528\u7684\u547D\u4EE4\uFF1A",
138628
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",
138629
138581
  stop: "\xB7 /stop \u2014\u2014 \u505C\u6389\u6B63\u5728\u8DD1\u7684\u8FD9\u4E00\u8F6E\uFF0C\u4F1A\u8BDD\u7559\u7740",
138630
138582
  status: "\xB7 /status \u2014\u2014 \u73B0\u5728\u5728\u5E72\u4EC0\u4E48",
138631
138583
  new: "\xB7 /new \u2014\u2014 \u5FD8\u6389\u5F53\u524D\u4F1A\u8BDD\uFF0C\u4E0B\u4E00\u53E5\u5F00\u65B0\u7684",
138632
- 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",
138633
138585
  thread: "\xB7 /thread \u2014\u2014 \u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
138634
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",
138635
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",
@@ -138753,11 +138705,6 @@ var zh_CN_default = {
138753
138705
  title: "\u9009\u4E00\u6761\u4F1A\u8BDD",
138754
138706
  hint: "\u70B9\u4E00\u6761\u5207\u8FC7\u53BB\u3002"
138755
138707
  },
138756
- teams: {
138757
- title: "\u9009\u4E00\u652F\u961F",
138758
- hint: "\u70B9\u4E00\u652F\u961F\uFF0C\u63A5\u4E0B\u6765\u7684\u6D3B\u6D3E\u7ED9\u5B83\u3002",
138759
- unavailable: "\u8BFB\u4E0D\u5230\u56E2\u961F\u5217\u8868\u3002"
138760
- },
138761
138708
  models: {
138762
138709
  title: "\u9009\u6A21\u578B"
138763
138710
  },
@@ -138928,7 +138875,7 @@ var zh_CN_default = {
138928
138875
  model: "\u770B\u6216\u6362\u6A21\u578B",
138929
138876
  plan: "\u5F00\u5173\u8BA1\u5212\u6A21\u5F0F",
138930
138877
  repo: "\u9009\u8FD9\u4E2A\u804A\u5929\u5728\u54EA\u4E2A\u9879\u76EE\u4E0A\u5E72\u6D3B",
138931
- 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",
138932
138879
  thread: "\u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
138933
138880
  panel: "\u6253\u5F00\u547D\u4EE4\u9762\u677F",
138934
138881
  help: "\u5217\u51FA\u5168\u90E8\u547D\u4EE4"
@@ -138992,6 +138939,14 @@ var zh_CN_default = {
138992
138939
  removeConfirm: "\u5220\u9664\u8FD9\u4E2A\u76EE\u6807",
138993
138940
  removeFailed: "\u8FD9\u4E2A\u76EE\u6807\u6CA1\u5220\u6389\u3002"
138994
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}}"
138995
138950
  }
138996
138951
  };
138997
138952
 
@@ -139014,8 +138969,8 @@ var interpolate = (template, params) => params === void 0 ? template : template.
139014
138969
  var makeTranslate = (language) => {
139015
138970
  const catalog = CATALOGS[language];
139016
138971
  const optional = (key, params) => {
139017
- const text3 = lookup(catalog, key);
139018
- 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);
139019
138974
  };
139020
138975
  return Object.assign(
139021
138976
  (key, params) => optional(key, params) ?? key,
@@ -139129,22 +139084,16 @@ var notificationChatKeys = (state, threadId, projectId) => {
139129
139084
 
139130
139085
  // src/threadMessages.ts
139131
139086
  import {
139132
- isThreadNotFound
139087
+ isThreadNotFound,
139088
+ threadMessagesNewestFirst
139133
139089
  } from "@ycodium-ai/plugin-api";
139134
139090
  var PAGE_SIZE = 20;
139135
139091
  async function* newestFirst(threads, threadId) {
139136
- let cursor = null;
139137
- do {
139138
- let page;
139139
- try {
139140
- page = await threads.messages.list({ threadId, limit: PAGE_SIZE, cursor });
139141
- } catch (error) {
139142
- if (isThreadNotFound(error)) return;
139143
- throw error;
139144
- }
139145
- yield* page.items;
139146
- cursor = page.nextCursor;
139147
- } while (cursor !== null);
139092
+ try {
139093
+ yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
139094
+ } catch (error) {
139095
+ if (!isThreadNotFound(error)) throw error;
139096
+ }
139148
139097
  }
139149
139098
  async function attachmentsOf(threads, threadId, message) {
139150
139099
  const collected = [...message.attachments ?? []];
@@ -139189,7 +139138,6 @@ var outcomeOfSession = (status) => {
139189
139138
  if (status === "interrupted" || status === "stopped") return "stopped";
139190
139139
  return "done";
139191
139140
  };
139192
- var outcomeOfTeamRun = (state) => state === "settled" ? "done" : state === "failed" ? "failed" : "stopped";
139193
139141
 
139194
139142
  // src/notifications.ts
139195
139143
  var THREAD_PROJECT_CACHE_LIMIT = 256;
@@ -139215,7 +139163,8 @@ var makeNotifications = (core, deps) => {
139215
139163
  const binding = bindingForChatKey(chatKey);
139216
139164
  return binding === void 0 ? [] : [binding];
139217
139165
  });
139218
- 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);
139219
139168
  const threadsWithSomethingToReport = /* @__PURE__ */ new Set();
139220
139169
  host.reactor({
139221
139170
  name: "im.assistant-messages",
@@ -139249,13 +139198,12 @@ var makeNotifications = (core, deps) => {
139249
139198
  if (thread !== null && final !== void 0) {
139250
139199
  const attachments = await attachmentsOf(host.threads, threadId, final);
139251
139200
  for (const binding of reporters) {
139252
- const text3 = streamsTo(binding, threadId) ? "" : `${thread.title}
139201
+ const text4 = streamsTo(binding, threadId) ? "" : `${thread.title}
139253
139202
 
139254
139203
  ${final.text}`;
139255
- const owns = chatOf(core.state, chatKeyOf(binding)).threadId === threadId;
139256
139204
  await deliver(
139257
- owns ? await anchors.anchored(binding, threadId, final.turnId) : binding,
139258
- text3,
139205
+ owns(binding, threadId) ? await anchors.anchored(binding, threadId, final.turnId) : binding,
139206
+ text4,
139259
139207
  attachments
139260
139208
  );
139261
139209
  }
@@ -139336,9 +139284,9 @@ var PANEL_COMMANDS = [
139336
139284
  id: "team",
139337
139285
  category: "target",
139338
139286
  line: "/team",
139339
- kind: "showTargets",
139287
+ kind: "selectTeam",
139340
139288
  labelKey: "panel.cmd.team",
139341
- action: { op: "open", arg: "teams" }
139289
+ action: { op: "run", arg: "team" }
139342
139290
  },
139343
139291
  {
139344
139292
  id: "thread",
@@ -139402,12 +139350,7 @@ var panelCommandsFor = (mode = "default") => mode === "minimal" ? PANEL_COMMANDS
139402
139350
  var PANEL_PAGE_SIZE = 8;
139403
139351
  var PANEL_CARD_LIMIT = 200;
139404
139352
  var LABEL_MAX_CHARS = 60;
139405
- var PICK_KINDS = /* @__PURE__ */ new Set([
139406
- "sessions",
139407
- "teams",
139408
- "models",
139409
- "projects"
139410
- ]);
139353
+ var PICK_KINDS = /* @__PURE__ */ new Set(["sessions", "models", "projects"]);
139411
139354
  var clip2 = (label) => {
139412
139355
  const chars = Array.from(label);
139413
139356
  return chars.length <= LABEL_MAX_CHARS ? label : `${chars.slice(0, LABEL_MAX_CHARS - 1).join("")}\u2026`;
@@ -139437,10 +139380,10 @@ var makePanelController = (deps) => {
139437
139380
  action: { op, arg },
139438
139381
  ...danger === true ? { danger } : {}
139439
139382
  });
139440
- const busyCard = (title, text3) => ({
139383
+ const busyCard = (title, text4) => ({
139441
139384
  title,
139442
139385
  tone: "busy",
139443
- text: text3,
139386
+ text: text4,
139444
139387
  groups: [],
139445
139388
  nav: []
139446
139389
  });
@@ -139517,16 +139460,6 @@ ${t("panel.projects.hint")}`;
139517
139460
  )
139518
139461
  });
139519
139462
  }
139520
- case "teams":
139521
- return pickerCard({
139522
- kind: "teams",
139523
- page: view.page,
139524
- depth,
139525
- text: view.teams === null ? t("panel.teams.unavailable") : view.teams.length === 0 ? t("command.noTeams") : t("panel.teams.hint"),
139526
- items: (view.teams ?? []).map(
139527
- (team) => button(team.title, "pick", `teams:${team.teamId}`)
139528
- )
139529
- });
139530
139463
  case "projects":
139531
139464
  return pickerCard({
139532
139465
  kind: "projects",
@@ -139580,17 +139513,15 @@ ${t("panel.projects.hint")}`;
139580
139513
  }
139581
139514
  }
139582
139515
  });
139583
- const placeholder = (entry, title, text3) => {
139516
+ const placeholder = (entry, title, text4) => {
139584
139517
  void post(entry.cardId, async () => {
139585
- await deps.surface(entry.chatKey)?.update(entry.cardId, busyCard(title, text3));
139518
+ await deps.surface(entry.chatKey)?.update(entry.cardId, busyCard(title, text4));
139586
139519
  });
139587
139520
  };
139588
139521
  const loadView = async (chatKey, kind) => {
139589
139522
  switch (kind) {
139590
139523
  case "sessions":
139591
139524
  return { kind, page: 0, rows: await deps.loadSessions(chatKey) };
139592
- case "teams":
139593
- return { kind, page: 0, teams: await deps.loadTeams(chatKey) };
139594
139525
  case "models":
139595
139526
  return { kind, page: 0, models: await deps.loadModels(chatKey) };
139596
139527
  case "projects":
@@ -139714,7 +139645,7 @@ ${t("panel.projects.hint")}`;
139714
139645
  return null;
139715
139646
  case "page": {
139716
139647
  const page = Number(arg);
139717
- 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) {
139718
139649
  navigate(entry, () => {
139719
139650
  entry.stack[entry.stack.length - 1] = { ...top, page };
139720
139651
  });
@@ -139737,7 +139668,7 @@ ${t("panel.projects.hint")}`;
139737
139668
  case "pick": {
139738
139669
  const split = arg.indexOf(":");
139739
139670
  const key = split < 0 ? "" : arg.slice(split + 1);
139740
- 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(
139741
139672
  (choice) => `${choice.instanceId}/${choice.model}` === key
139742
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;
139743
139674
  if (line === null) {
@@ -139764,7 +139695,6 @@ var makePanelWiring = (core, deps) => {
139764
139695
  const { host, t, adapterFor, deliver, bindingOf: bindingOf2, bindingForChatKey } = core;
139765
139696
  const { enqueueForChat, handleCommand } = deps;
139766
139697
  const { sessionRowsFor, listedByChat } = deps.sessions;
139767
- const { fetchTeams } = deps.teams;
139768
139698
  const { currentModelOf } = deps.modelPlan;
139769
139699
  const { projectRowsFor, listedProjectsByChat } = deps.rows;
139770
139700
  const panel = makePanelController({
@@ -139790,10 +139720,6 @@ var makePanelWiring = (core, deps) => {
139790
139720
  listedByChat.set(chatKey, listedThreadIds(rows));
139791
139721
  return rows;
139792
139722
  },
139793
- loadTeams: async (chatKey) => {
139794
- const binding = bindingForChatKey(chatKey);
139795
- return binding === void 0 ? null : fetchTeams(binding);
139796
- },
139797
139723
  loadModels: async (chatKey) => {
139798
139724
  const binding = bindingForChatKey(chatKey);
139799
139725
  const instances = await host.providers.listInstances().catch(() => null);
@@ -139809,7 +139735,7 @@ var makePanelWiring = (core, deps) => {
139809
139735
  runLine: async (chatKey, line) => {
139810
139736
  const binding = bindingForChatKey(chatKey);
139811
139737
  if (binding === void 0) return;
139812
- await handleCommand(binding, line, await fetchTeams(binding) ?? []);
139738
+ await handleCommand(binding, line);
139813
139739
  },
139814
139740
  sendHelpText: async (chatKey) => {
139815
139741
  const binding = bindingForChatKey(chatKey);
@@ -139900,12 +139826,12 @@ var makeFailureNotices = (core) => {
139900
139826
  const reference2 = diagnosticRef("msg");
139901
139827
  core.host.log.warn("chat turn failed", { threadId, reference: reference2 });
139902
139828
  const said = reasonOf2(detail);
139903
- const text3 = said === "" ? core.t("reply.turnFailedNoDetail", { ref: reference2 }) : core.t("reply.turnFailed", { detail: said, ref: reference2 });
139904
- return text3;
139829
+ const text4 = said === "" ? core.t("reply.turnFailedNoDetail", { ref: reference2 }) : core.t("reply.turnFailed", { detail: said, ref: reference2 });
139830
+ return text4;
139905
139831
  },
139906
139832
  /** 正在画的那一轮的卡会说这次失败:寄存给它。 */
139907
- holdForCard: (threadId, turnId, text3) => {
139908
- heldForCard.set(threadId, { turnId, text: text3 });
139833
+ holdForCard: (threadId, turnId, text4) => {
139834
+ heldForCard.set(threadId, { turnId, text: text4 });
139909
139835
  },
139910
139836
  /**
139911
139837
  * 卡收尾(无论怎么收的都调):清掉这条会话的寄存。失败收尾时,寄存是这一轮的就用它(同一个号),
@@ -139941,8 +139867,8 @@ var STEP_KIND_BY_ITEM_TYPE = {
139941
139867
  };
139942
139868
  var stepKindOf = (itemType) => STEP_KIND_BY_ITEM_TYPE[itemType] ?? "tool";
139943
139869
  var TURN_TITLE_MAX_CHARS = 40;
139944
- var turnTitleOf = (text3) => {
139945
- const oneLine = text3.replace(/\s+/g, " ").trim();
139870
+ var turnTitleOf = (text4) => {
139871
+ const oneLine = text4.replace(/\s+/g, " ").trim();
139946
139872
  return oneLine.length <= TURN_TITLE_MAX_CHARS ? oneLine : `${oneLine.slice(0, TURN_TITLE_MAX_CHARS)}\u2026`;
139947
139873
  };
139948
139874
  var buildTurnView = (input) => {
@@ -139950,7 +139876,7 @@ var buildTurnView = (input) => {
139950
139876
  const steps = [];
139951
139877
  if (progress.thinking.active || progress.thinking.chars > 0) steps.push("think");
139952
139878
  for (const tool of progress.tools) steps.push(stepKindOf(tool.itemType));
139953
- 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");
139954
139880
  const runningTool = progress.tools.findLast((tool) => tool.status === "running");
139955
139881
  const running = input.status === "working" && runningTool !== void 0 && runningTool.label !== "" ? runningTool.label : null;
139956
139882
  return {
@@ -140003,9 +139929,9 @@ var makeTurnCards = (deps) => {
140003
139929
  texts.set(segment.messageId, known);
140004
139930
  continue;
140005
139931
  }
140006
- const text3 = await deps.readText(segment.messageId) ?? "";
140007
- texts.set(segment.messageId, text3);
140008
- 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);
140009
139935
  }
140010
139936
  return texts;
140011
139937
  };
@@ -140265,8 +140191,8 @@ var makeReplyCards = (core, failures, anchors) => {
140265
140191
  fallback: async (threadId, turnId, chatKey, view) => {
140266
140192
  const binding = bindingForChatKey(chatKey);
140267
140193
  if (binding === void 0) return;
140268
- const text3 = [view.body, view.errorText ?? ""].filter((part) => part !== "").join("\n\n");
140269
- 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);
140270
140196
  },
140271
140197
  schedule: (run, delayMs) => {
140272
140198
  const timer = setTimeout(run, delayMs);
@@ -140345,8 +140271,8 @@ var makeDeliverySender = (core, config2) => {
140345
140271
  };
140346
140272
 
140347
140273
  // src/sendFile.ts
140348
- var failure = (code2, text3) => ({
140349
- text: text3,
140274
+ var failure = (code2, text4) => ({
140275
+ text: text4,
140350
140276
  isError: true,
140351
140277
  errorCode: code2
140352
140278
  });
@@ -140499,15 +140425,14 @@ var makeSessions = (core) => {
140499
140425
  const pendingAttachByChat = /* @__PURE__ */ new Map();
140500
140426
  const rowFromThread = (thread, chatKey, origin) => {
140501
140427
  if (thread.archivedAt != null) return null;
140428
+ const owner = chatOfThread(core.state, thread.threadId);
140502
140429
  return {
140503
140430
  threadId: thread.threadId,
140504
140431
  title: thread.title,
140505
140432
  updatedAt: thread.updatedAt,
140506
140433
  running: isSessionRunning(thread.sessionStatus),
140507
140434
  current: chatOf(core.state, chatKey).threadId === thread.threadId,
140508
- elsewhere: Object.entries(core.state.chats).some(
140509
- ([otherKey, record2]) => otherKey !== chatKey && record2.threadId === thread.threadId
140510
- ),
140435
+ elsewhere: owner !== void 0 && owner !== chatKey,
140511
140436
  origin
140512
140437
  };
140513
140438
  };
@@ -140636,51 +140561,76 @@ var makeSessions = (core) => {
140636
140561
  return { listedByChat, sessionRowsFor, showSessions, resumeSession };
140637
140562
  };
140638
140563
 
140639
- // src/teamRuns.ts
140640
- var makeTeamRuns = (core, deps) => {
140641
- const { host, deliver } = core;
140642
- const { clearWorking } = deps;
140643
- const chatByRun = /* @__PURE__ */ new Map();
140644
- const fetchTeams = async (binding) => binding.projectId === "" ? [] : host.plugins.invoke({
140645
- pluginId: "teams",
140646
- command: "choices",
140647
- payload: { projectId: binding.projectId }
140648
- }).then(
140649
- (result) => Array.isArray(result) ? result.flatMap(
140650
- (row) => typeof row === "object" && row !== null && typeof row.teamId === "string" && typeof row.title === "string" ? [{ teamId: row.teamId, title: row.title }] : []
140651
- ) : null
140652
- ).catch(() => null);
140653
- const startTeamRun = async (binding, teamId, text3) => {
140654
- const commandId = crypto.randomUUID();
140655
- const runId = `run:${commandId}`;
140656
- 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) => {
140580
+ try {
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) => {
140657
140595
  try {
140658
- await host.plugins.invoke({
140659
- pluginId: "teams",
140660
- command: "run",
140596
+ const result = await host.plugins.invoke({
140597
+ pluginId: "team",
140598
+ command: "startGoal",
140661
140599
  payload: {
140662
- commandId,
140663
- teamId,
140664
140600
  projectId: binding.projectId,
140665
- goal: text3
140601
+ goal: message.text,
140602
+ requestId: teamGoalRequestId(binding, message.messageId)
140666
140603
  }
140667
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;
140668
140627
  } catch (error) {
140669
- chatByRun.delete(runId);
140670
- 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;
140671
140631
  }
140672
- host.log.info("chat started a team run", { bot: binding.displayName, teamId, runId });
140673
140632
  };
140674
- host.events.on("teams.run-ended", async (event) => {
140675
- const runId = event.data.runId;
140676
- if (typeof runId !== "string") return;
140677
- const binding = chatByRun.get(runId);
140678
- if (binding === void 0) return;
140679
- chatByRun.delete(runId);
140680
- await clearWorking(binding, chatKeyOf(binding), outcomeOfTeamRun(event.data.state));
140681
- await deliver(binding, event.summary);
140682
- });
140683
- return { fetchTeams, startTeamRun };
140633
+ return { hasRosterFor, startTeamGoal };
140684
140634
  };
140685
140635
 
140686
140636
  // src/telegramApi.ts
@@ -140774,19 +140724,19 @@ var unsupportedTypeOf = (message) => {
140774
140724
  return null;
140775
140725
  };
140776
140726
  var TELEGRAM_DOWNLOAD_LIMIT_BYTES = 20 * 1024 * 1024;
140777
- var splitForTelegram = (text3, limit = TELEGRAM_TEXT_MAX_CHARS) => splitMessage(text3, limit);
140727
+ var splitForTelegram = (text4, limit = TELEGRAM_TEXT_MAX_CHARS) => splitMessage(text4, limit);
140778
140728
  var nextOffset = (updates, current) => updates.reduce((offset, update) => Math.max(offset, update.update_id + 1), current);
140779
- var commandForBot = (text3, botUsername) => {
140780
- const match = text3.match(/^(\/[A-Za-z0-9_]+)@([A-Za-z0-9_]+)(?=\s|$)/);
140781
- 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;
140782
140732
  const [whole, command = "", addressee = ""] = match;
140783
140733
  if (botUsername !== null && addressee.toLowerCase() !== botUsername.toLowerCase()) {
140784
140734
  return null;
140785
140735
  }
140786
- return command + text3.slice(whole.length);
140736
+ return command + text4.slice(whole.length);
140787
140737
  };
140788
- var mentionedNames = (text3) => Array.from(
140789
- 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),
140790
140740
  (match) => (match[1] ?? "").toLowerCase()
140791
140741
  );
140792
140742
  var passesGroupGate2 = (input) => {
@@ -140924,8 +140874,8 @@ var makeTelegramApi = (input) => {
140924
140874
  },
140925
140875
  POLL_CALL_TIMEOUT_MS
140926
140876
  ),
140927
- sendMessage: async (chatId, text3) => {
140928
- for (const chunk of splitForTelegram(text3)) {
140877
+ sendMessage: async (chatId, text4) => {
140878
+ for (const chunk of splitForTelegram(text4)) {
140929
140879
  await call("sendMessage", { ...target(chatId), text: chunk });
140930
140880
  }
140931
140881
  },
@@ -140933,7 +140883,7 @@ var makeTelegramApi = (input) => {
140933
140883
  * 发一条消息,回它的 id。调用方保证 `text` 不超过单条上限(边写边更新的回复要自己
140934
140884
  * 在上限处翻篇,这里不替它切)。带 `rows` 就挂一块内联键盘。
140935
140885
  */
140936
- sendOne: (chatId, text3, rows) => sendSingle("sendMessage", chatId, { text: text3 }, rows),
140886
+ sendOne: (chatId, text4, rows) => sendSingle("sendMessage", chatId, { text: text4 }, rows),
140937
140887
  /**
140938
140888
  * 发一条富文本,回它的 id。`markdown` 已是平台要的样子。带 `rows` 就挂一块内联键盘。
140939
140889
  * 调用方保证不超富文本单条上限(这里不替它切)。
@@ -140943,23 +140893,23 @@ var makeTelegramApi = (input) => {
140943
140893
  * 改一条已发出的消息。内容没变(`message is not modified`)当成功。`rows` 不给就是
140944
140894
  * 去掉按钮:改了文字又要保留按钮的调用方得自己再传一次。
140945
140895
  */
140946
- editMessage: (chatId, messageId, text3, rows = []) => editSingle(chatId, messageId, { text: text3 }, rows),
140896
+ editMessage: (chatId, messageId, text4, rows = []) => editSingle(chatId, messageId, { text: text4 }, rows),
140947
140897
  /**
140948
140898
  * 把一条已发出的消息改成富文本。不带 `text`,只带 `rich_message`。内容没变
140949
140899
  * (`message is not modified`)当成功。`rows` 不给就是去掉按钮。
140950
140900
  */
140951
140901
  editRich: (chatId, messageId, markdown, rows = []) => editSingle(chatId, messageId, { rich_message: { markdown } }, rows),
140952
140902
  /** 带按钮的审批消息,一行一个按钮;回消息 id,之后才改得了它(平台没给就是 null)。 */
140953
- sendButtons: (chatId, text3, buttons) => sendSingle(
140903
+ sendButtons: (chatId, text4, buttons) => sendSingle(
140954
140904
  "sendMessage",
140955
140905
  chatId,
140956
- { text: text3 },
140906
+ { text: text4 },
140957
140907
  buttons.map((button) => [{ text: button.label, data: button.token }])
140958
140908
  ),
140959
140909
  /** 答完点击,不然客户端上那个按钮一直转圈。带 `text` 时点击者会看到一句提示。 */
140960
- answerCallback: (callbackQueryId, text3) => call("answerCallbackQuery", {
140910
+ answerCallback: (callbackQueryId, text4) => call("answerCallbackQuery", {
140961
140911
  callback_query_id: callbackQueryId,
140962
- ...text3 === void 0 ? {} : { text: text3 }
140912
+ ...text4 === void 0 ? {} : { text: text4 }
140963
140913
  }),
140964
140914
  sendPhoto: (chatId, photo) => upload("sendPhoto", "photo", chatId, photo),
140965
140915
  /** 以文件形式发(不压缩、不限尺寸比例):什么类型都行,音频与视频也走这条。 */
@@ -141069,9 +141019,9 @@ var toTelegramRichMarkdown = (value2) => {
141069
141019
 
141070
141020
  // src/plainTurnText.ts
141071
141021
  var RUNNING_LABEL_MAX_CHARS = 200;
141072
- var clip3 = (text3, max) => {
141073
- const chars = Array.from(text3);
141074
- 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`;
141075
141025
  };
141076
141026
  var turnTextParts = (view, t) => {
141077
141027
  const names = view.steps.map((kind) => t(`card.step.${kind}`));
@@ -141098,8 +141048,8 @@ var makeTurnWriter = (deps) => {
141098
141048
  let liveText = null;
141099
141049
  let frozen = 0;
141100
141050
  let consumed = 0;
141101
- const put = async (text3) => {
141102
- 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);
141103
141053
  if (live === null) {
141104
141054
  const id = await deps.messages.send(bounded);
141105
141055
  if (id === null) throw new Error("telegram sent a message without an id");
@@ -141241,18 +141191,18 @@ var makeTelegramAdapter = (deps) => {
141241
141191
  limit: TELEGRAM_TEXT_MAX_CHARS,
141242
141192
  ...resume === void 0 ? {} : { resume },
141243
141193
  messages: {
141244
- send: (text3) => withRichFallback(
141245
- toTelegramRichMarkdown(text3),
141194
+ send: (text4) => withRichFallback(
141195
+ toTelegramRichMarkdown(text4),
141246
141196
  async (markdown) => (await apiFor(slot.binding)).sendRichOne(chatId, markdown),
141247
- async () => (await apiFor(slot.binding)).sendOne(chatId, text3)
141197
+ async () => (await apiFor(slot.binding)).sendOne(chatId, text4)
141248
141198
  ),
141249
- edit: (messageId, text3) => withRichFallback(
141250
- toTelegramRichMarkdown(text3),
141199
+ edit: (messageId, text4) => withRichFallback(
141200
+ toTelegramRichMarkdown(text4),
141251
141201
  async (markdown) => {
141252
141202
  await (await apiFor(slot.binding)).editRich(chatId, messageId, markdown);
141253
141203
  },
141254
141204
  async () => {
141255
- await (await apiFor(slot.binding)).editMessage(chatId, messageId, text3);
141205
+ await (await apiFor(slot.binding)).editMessage(chatId, messageId, text4);
141256
141206
  }
141257
141207
  )
141258
141208
  }
@@ -141324,17 +141274,17 @@ var makeTelegramAdapter = (deps) => {
141324
141274
  continue;
141325
141275
  }
141326
141276
  const resource = resourceOf2(message);
141327
- const text3 = commandForBot(
141277
+ const text4 = commandForBot(
141328
141278
  (message.text ?? message.caption ?? "").trim(),
141329
141279
  botUsername
141330
141280
  );
141331
- if (text3 === null) {
141281
+ if (text4 === null) {
141332
141282
  offset = nextOffset([update], offset);
141333
141283
  continue;
141334
141284
  }
141335
141285
  const gated = !passesGroupGate2({
141336
141286
  message,
141337
- text: text3,
141287
+ text: text4,
141338
141288
  hasResource: resource !== null,
141339
141289
  botUsername: botUsername ?? null,
141340
141290
  groupMention: binding.groupMention
@@ -141351,7 +141301,7 @@ var makeTelegramAdapter = (deps) => {
141351
141301
  offset = nextOffset([update], offset);
141352
141302
  const senderId = message.from === void 0 ? null : String(message.from.id);
141353
141303
  const chatKind = message.chat.type === "private" ? "private" : "group";
141354
- if (text3 === "" && resource === null) {
141304
+ if (text4 === "" && resource === null) {
141355
141305
  const unsupported = unsupportedTypeOf(message);
141356
141306
  if (unsupported === null) continue;
141357
141307
  handlers.onMessage({
@@ -141371,7 +141321,7 @@ var makeTelegramAdapter = (deps) => {
141371
141321
  chatId: chatIdOf(message),
141372
141322
  ...parentChatId === void 0 ? {} : { parentChatId },
141373
141323
  senderId,
141374
- text: text3,
141324
+ text: text4,
141375
141325
  chatKind,
141376
141326
  resources: resource === null ? [] : [
141377
141327
  {
@@ -141403,9 +141353,9 @@ var makeTelegramAdapter = (deps) => {
141403
141353
  }
141404
141354
  };
141405
141355
  },
141406
- sendText: async (binding, text3) => {
141356
+ sendText: async (binding, text4) => {
141407
141357
  const api = await apiFor(binding);
141408
- await api.sendMessage(binding.chatId, text3);
141358
+ await api.sendMessage(binding.chatId, text4);
141409
141359
  },
141410
141360
  checkConnection: async (bot) => {
141411
141361
  const token = tokenOf(bot);
@@ -141590,7 +141540,7 @@ ${line}`
141590
141540
  // src/turns.ts
141591
141541
  import { projectOrNull as projectOrNull2, threadOrNull as threadOrNull7 } from "@ycodium-ai/plugin-api";
141592
141542
  var TITLE_MAX_CHARS = 72;
141593
- 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";
141594
141544
  var makeTurns = (core, deps) => {
141595
141545
  const { host, t, commit, bindChat, deliver } = core;
141596
141546
  const { queueFlow, rememberThreadProject } = deps;
@@ -141663,8 +141613,8 @@ var makeTurns = (core, deps) => {
141663
141613
  };
141664
141614
  const startTurn = async (binding, message) => {
141665
141615
  const chatKey = chatKeyOf(binding);
141666
- const text3 = message.text;
141667
- 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");
141668
141618
  if (threadId === null) return null;
141669
141619
  const carried = waitingFor(chatKey, threadId);
141670
141620
  pendingByChat.delete(chatKey);
@@ -141702,12 +141652,12 @@ var makeTurns = (core, deps) => {
141702
141652
  message: {
141703
141653
  messageId: userMessageId,
141704
141654
  role: "user",
141705
- text: notes.length === 0 ? text3 : [text3, ...notes].join("\n"),
141655
+ text: notes.length === 0 ? text4 : [text4, ...notes].join("\n"),
141706
141656
  attachments: attachments.map(
141707
141657
  (attachment) => attachment.type === "image" ? { ...attachment, type: "image" } : { ...attachment, type: "file" }
141708
141658
  )
141709
141659
  },
141710
- titleSeed: titleFrom(text3 || attachments[0]?.name || "Chat"),
141660
+ titleSeed: titleFrom(text4 || attachments[0]?.name || "Chat"),
141711
141661
  runtimeMode: binding.runtimeMode,
141712
141662
  interactionMode: interactionModeOf(chatKey),
141713
141663
  ...intentAction !== void 0 ? { intentAction } : {}
@@ -141726,7 +141676,7 @@ var makeTurns = (core, deps) => {
141726
141676
  chatKey,
141727
141677
  threadId,
141728
141678
  userMessageId,
141729
- text3.trim() || attachments[0]?.name || message.resources[0]?.name || "",
141679
+ text4.trim() || attachments[0]?.name || message.resources[0]?.name || "",
141730
141680
  binding.reply
141731
141681
  );
141732
141682
  return threadId;
@@ -141986,7 +141936,7 @@ var registerSettingsRowActions = (ctx, adapters) => {
141986
141936
  };
141987
141937
 
141988
141938
  // src/settingsView.ts
141989
- var isRecord2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
141939
+ var isRecord3 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
141990
141940
  var hasStoredSecret = (row, key) => {
141991
141941
  const value2 = row[key];
141992
141942
  return typeof value2 === "string" && value2 !== "";
@@ -142004,10 +141954,10 @@ var targetTable = () => ({
142004
141954
  });
142005
141955
  var targetViews = (config2) => {
142006
141956
  const table2 = config2[DELIVERY_TARGETS_FIELD];
142007
- if (!isRecord2(table2)) return [];
141957
+ if (!isRecord3(table2)) return [];
142008
141958
  const columns = deliveryTargetColumns();
142009
141959
  return Object.entries(table2).flatMap(([rowId, raw]) => {
142010
- if (!isRecord2(raw)) return [];
141960
+ if (!isRecord3(raw)) return [];
142011
141961
  const issues = targetIssues(raw);
142012
141962
  const values = Object.fromEntries(
142013
141963
  columns.map((column) => [column.key, readString(raw, column.key)])
@@ -142019,9 +141969,9 @@ var buildSettingsView = (config2, adapters) => {
142019
141969
  const columns = buildBotColumns(adapters);
142020
141970
  const table2 = config2[BOTS_FIELD];
142021
141971
  const bots = [];
142022
- if (isRecord2(table2)) {
141972
+ if (isRecord3(table2)) {
142023
141973
  for (const [rowId, raw] of Object.entries(table2)) {
142024
- if (!isRecord2(raw)) continue;
141974
+ if (!isRecord3(raw)) continue;
142025
141975
  const platform = platformOf(raw);
142026
141976
  const values = {};
142027
141977
  const secrets = {};
@@ -142084,10 +142034,10 @@ var applyRowEdit = (config2, { field, columns }, edit) => {
142084
142034
  for (const key of clearSecrets) {
142085
142035
  if (!secretColumns.has(key)) return columnError("not-a-secret", key);
142086
142036
  }
142087
- const table2 = isRecord2(config2[field]) ? config2[field] : {};
142037
+ const table2 = isRecord3(config2[field]) ? config2[field] : {};
142088
142038
  const requested = edit.rowId;
142089
142039
  const current = requested === void 0 ? {} : Object.hasOwn(table2, requested) ? table2[requested] : void 0;
142090
- if (!isRecord2(current)) return { ok: false, code: "unknown-row" };
142040
+ if (!isRecord3(current)) return { ok: false, code: "unknown-row" };
142091
142041
  const rowId = requested ?? nextRowId(table2);
142092
142042
  const nextRow = { ...current, ...edit.values };
142093
142043
  const clearing = clearSecrets.filter((key) => !Object.hasOwn(secrets, key));
@@ -142105,7 +142055,7 @@ var applyBotEdit = (config2, adapters, edit) => applyRowEdit(config2, { field: B
142105
142055
  var applyTargetEdit = (config2, edit) => applyRowEdit(config2, targetTable(), edit);
142106
142056
  var removeRow = (config2, field, rowId) => {
142107
142057
  const table2 = config2[field];
142108
- if (!isRecord2(table2) || !Object.hasOwn(table2, rowId)) return null;
142058
+ if (!isRecord3(table2) || !Object.hasOwn(table2, rowId)) return null;
142109
142059
  const nextTable = { ...table2 };
142110
142060
  delete nextTable[rowId];
142111
142061
  return { ...config2, [field]: nextTable };
@@ -142314,12 +142264,12 @@ var makeWechatAdapter = (deps) => {
142314
142264
  });
142315
142265
  return null;
142316
142266
  },
142317
- answerByText: (_binding, text3, options) => answerByNumber(text3, options)
142267
+ answerByText: (_binding, text4, options) => answerByNumber(text4, options)
142318
142268
  };
142319
142269
  };
142320
142270
 
142321
142271
  // src/wecomUpload.ts
142322
- import * as NodeCrypto2 from "node:crypto";
142272
+ import * as NodeCrypto3 from "node:crypto";
142323
142273
  var WECOM_CHUNK_BYTES = 512 * 1024;
142324
142274
  var WECOM_MAX_CHUNKS = 100;
142325
142275
  var WECOM_MIN_UPLOAD_BYTES = 5;
@@ -142352,7 +142302,7 @@ var uploadWecomMedia = async (input) => {
142352
142302
  filename: clampName(input.filename),
142353
142303
  total_size: bytes.byteLength,
142354
142304
  total_chunks: totalChunks,
142355
- md5: NodeCrypto2.createHash("md5").update(bytes).digest("hex")
142305
+ md5: NodeCrypto3.createHash("md5").update(bytes).digest("hex")
142356
142306
  });
142357
142307
  const uploadId = init.upload_id;
142358
142308
  if (typeof uploadId !== "string" || uploadId === "") {
@@ -142424,21 +142374,21 @@ var parseWecomMessage = (frame, botId) => {
142424
142374
  const ownIds = [...new Set([body.aibotid, botId].filter((id) => Boolean(id)))];
142425
142375
  const stripOwn = (value2) => ownIds.reduce((rest, id) => rest.replaceAll(`@${id}`, ""), value2);
142426
142376
  let mentionSource = "";
142427
- let text3 = "";
142377
+ let text4 = "";
142428
142378
  const resources = [];
142429
142379
  switch (body.msgtype) {
142430
142380
  case "text": {
142431
142381
  const raw = body.text?.content;
142432
142382
  if (typeof raw !== "string") return null;
142433
142383
  mentionSource = raw;
142434
- text3 = stripOwn(raw).trim();
142384
+ text4 = stripOwn(raw).trim();
142435
142385
  break;
142436
142386
  }
142437
142387
  case "voice": {
142438
142388
  const transcript = body.voice?.content;
142439
142389
  if (typeof transcript !== "string" || transcript.trim() === "") return null;
142440
142390
  mentionSource = transcript;
142441
- text3 = stripOwn(transcript).trim();
142391
+ text4 = stripOwn(transcript).trim();
142442
142392
  break;
142443
142393
  }
142444
142394
  case "image":
@@ -142472,7 +142422,7 @@ var parseWecomMessage = (frame, botId) => {
142472
142422
  }
142473
142423
  }
142474
142424
  if (parts.length === 0) return null;
142475
- text3 = parts.join("\n");
142425
+ text4 = parts.join("\n");
142476
142426
  break;
142477
142427
  }
142478
142428
  default:
@@ -142484,14 +142434,14 @@ var parseWecomMessage = (frame, botId) => {
142484
142434
  messageId,
142485
142435
  chatId,
142486
142436
  senderUserId: body.from?.userid ?? null,
142487
- text: text3,
142437
+ text: text4,
142488
142438
  resources,
142489
142439
  requestId: frame.headers?.req_id ?? null,
142490
142440
  chatType: mentioned ? "single" : chatType,
142491
142441
  conversation: chatType === "group" ? "group" : "single"
142492
142442
  };
142493
142443
  };
142494
- var splitForWecom = (text3, limit = WECOM_TEXT_MAX_CHARS) => splitMessage(text3, limit);
142444
+ var splitForWecom = (text4, limit = WECOM_TEXT_MAX_CHARS) => splitMessage(text4, limit);
142495
142445
  var decoder = new TextDecoder();
142496
142446
  var runWecomClient = (input) => {
142497
142447
  let sequence = 0;
@@ -142593,8 +142543,8 @@ var runWecomClient = (input) => {
142593
142543
  return false;
142594
142544
  }
142595
142545
  );
142596
- const sendText = async (chatId, text3) => {
142597
- for (const [index, content] of splitForWecom(text3).entries()) {
142546
+ const sendText = async (chatId, text4) => {
142547
+ for (const [index, content] of splitForWecom(text4).entries()) {
142598
142548
  const inboundRequestId = index === 0 ? pendingRequests.get(chatId) : void 0;
142599
142549
  if (inboundRequestId !== void 0) {
142600
142550
  pendingRequests.delete(chatId);
@@ -142724,7 +142674,7 @@ var runWecomClient = (input) => {
142724
142674
  };
142725
142675
 
142726
142676
  // src/wecomMedia.ts
142727
- import * as NodeCrypto3 from "node:crypto";
142677
+ import * as NodeCrypto4 from "node:crypto";
142728
142678
 
142729
142679
  // src/wecomPadding.ts
142730
142680
  var PADDING_BLOCK = 32;
@@ -142755,7 +142705,7 @@ var decryptWecomMedia = (cipher, aesKey) => {
142755
142705
  if (cipher.byteLength === 0 || cipher.byteLength % AES_BLOCK !== 0) {
142756
142706
  throw new WecomDecryptError("the ciphertext is not a whole number of blocks");
142757
142707
  }
142758
- 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));
142759
142709
  decipher.setAutoPadding(false);
142760
142710
  const plain = Buffer.concat([decipher.update(cipher), decipher.final()]);
142761
142711
  const unpadded = stripPadding(plain);
@@ -142955,12 +142905,12 @@ ${kept}`;
142955
142905
  }
142956
142906
  };
142957
142907
  },
142958
- sendText: async (binding, text3) => {
142908
+ sendText: async (binding, text4) => {
142959
142909
  const client = clients.get(binding.rowId);
142960
142910
  if (client === void 0) {
142961
142911
  throw new ImNotConnectedError(`wecom bot '${binding.displayName}' has no connection.`);
142962
142912
  }
142963
- await client.sendText(binding.chatId, text3);
142913
+ await client.sendText(binding.chatId, text4);
142964
142914
  },
142965
142915
  checkConnection: async (bot) => {
142966
142916
  const { botId, botSecret, endpoint } = credentials2(bot);
@@ -143007,7 +142957,7 @@ ${kept}`;
143007
142957
  // 图 10 MB(只认 png / jpg / jpeg / gif)、文件 20 MB,来自企微官方文档「智能机器人长连接」。
143008
142958
  outboundLimits: { imageBytes: 10 * 1024 * 1024, fileBytes: 20 * 1024 * 1024, minBytes: 5 },
143009
142959
  imageMimeTypes: /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif"]),
143010
- answerByText: (_binding, text3, options) => answerByNumber(text3, options),
142960
+ answerByText: (_binding, text4, options) => answerByNumber(text4, options),
143011
142961
  fetchResource: async (binding, input) => {
143012
142962
  const parsed = JSON.parse(input.resource.key);
143013
142963
  const media = await fetchWecomMedia({
@@ -143060,8 +143010,8 @@ var normalizeApiBaseUrl = (value2) => {
143060
143010
  return raw.replace(/\/+$/u, "");
143061
143011
  };
143062
143012
  var byteLength = (value2) => Buffer.byteLength(value2, "utf8");
143063
- var splitUtf8ByBytes = (text3, maxBytes = WECOM_APP_TEXT_MAX_BYTES) => {
143064
- const value2 = typeof text3 === "string" ? text3 : "";
143013
+ var splitUtf8ByBytes = (text4, maxBytes = WECOM_APP_TEXT_MAX_BYTES) => {
143014
+ const value2 = typeof text4 === "string" ? text4 : "";
143065
143015
  if (value2 === "") return [""];
143066
143016
  const chunks = [];
143067
143017
  let current = "";
@@ -143277,7 +143227,7 @@ var WecomAppApi = class {
143277
143227
  import * as NodeHttp2 from "node:http";
143278
143228
 
143279
143229
  // src/wecomAppCrypto.ts
143280
- import * as NodeCrypto4 from "node:crypto";
143230
+ import * as NodeCrypto5 from "node:crypto";
143281
143231
  var AES_KEY_BYTES = 32;
143282
143232
  var RANDOM_BYTES = 16;
143283
143233
  var WecomAppCryptoError = class extends Error {
@@ -143300,13 +143250,13 @@ var timingSafeEqualString2 = (a, b) => {
143300
143250
  const left = Buffer.from(a);
143301
143251
  const right = Buffer.from(b);
143302
143252
  if (left.length === 0 || left.length !== right.length) return false;
143303
- return NodeCrypto4.timingSafeEqual(left, right);
143253
+ return NodeCrypto5.timingSafeEqual(left, right);
143304
143254
  };
143305
- 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");
143306
143256
  var verifySignature = (token, timestamp, nonce, encrypt, signature) => timingSafeEqualString2(computeSignature(token, timestamp, nonce, encrypt), signature);
143307
143257
  var decrypt = (encodingAESKey, encryptText, expectReceiveId) => {
143308
143258
  const { key, iv } = parseEncodingAESKey(encodingAESKey);
143309
- const decipher = NodeCrypto4.createDecipheriv("aes-256-cbc", key, iv);
143259
+ const decipher = NodeCrypto5.createDecipheriv("aes-256-cbc", key, iv);
143310
143260
  decipher.setAutoPadding(false);
143311
143261
  let deciphered;
143312
143262
  try {
@@ -143365,10 +143315,10 @@ var createWecomAppCrypto = (input) => {
143365
143315
  decrypt: (encryptText) => decrypt(encodingAESKey, encryptText, corpId).message
143366
143316
  };
143367
143317
  };
143368
- 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);
143369
143319
 
143370
143320
  // src/wecomAppParse.ts
143371
- var isRecord3 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
143321
+ var isRecord4 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
143372
143322
  var isXmlFormat = (raw) => {
143373
143323
  const trimmed = raw.trim();
143374
143324
  return trimmed.startsWith("<") && trimmed.endsWith(">");
@@ -143414,7 +143364,7 @@ var parseWecomAppPlainMessage = (raw) => {
143414
143364
  } catch {
143415
143365
  return null;
143416
143366
  }
143417
- if (!isRecord3(data)) return null;
143367
+ if (!isRecord4(data)) return null;
143418
143368
  const fromRaw = data["from"];
143419
143369
  const textRaw = data["text"];
143420
143370
  const imageRaw = data["image"];
@@ -143423,10 +143373,10 @@ var parseWecomAppPlainMessage = (raw) => {
143423
143373
  msgtype: String(data["msgtype"] ?? data["MsgType"] ?? "").toLowerCase(),
143424
143374
  createTime: data["createTime"] !== void 0 ? String(data["createTime"]) : data["CreateTime"] !== void 0 ? String(data["CreateTime"]) : void 0,
143425
143375
  agentId: data["agentid"] !== void 0 ? String(data["agentid"]) : data["AgentID"] !== void 0 ? String(data["AgentID"]) : void 0,
143426
- 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,
143427
143377
  to: typeof data["to"] === "string" ? data["to"] : void 0,
143428
- text: isRecord3(textRaw) ? { content: typeof textRaw["content"] === "string" ? textRaw["content"] : void 0 } : void 0,
143429
- 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,
143430
143380
  mediaId: typeof data["mediaid"] === "string" ? data["mediaid"] : void 0,
143431
143381
  recognition: typeof data["recognition"] === "string" ? data["recognition"] : void 0,
143432
143382
  event: String(data["event"] ?? data["eventtype"] ?? "").toLowerCase() || void 0,
@@ -143440,9 +143390,9 @@ var WECOM_APP_DEFAULT_CALLBACK_HOST = "127.0.0.1";
143440
143390
  var WECOM_APP_DEFAULT_CALLBACK_PORT = 30987;
143441
143391
  var WECOM_APP_CALLBACK_PATH_PREFIX = "/wecom-app-callback";
143442
143392
  var MAX_BODY_BYTES2 = 1 * 1024 * 1024;
143443
- var writeText = (res, status, text3, headers = {}) => {
143393
+ var writeText = (res, status, text4, headers = {}) => {
143444
143394
  if (res.writableEnded || res.destroyed) return;
143445
- const body = text3;
143395
+ const body = text4;
143446
143396
  res.writeHead(status, {
143447
143397
  "content-type": "text/plain; charset=utf-8",
143448
143398
  "content-length": Buffer.byteLength(body),
@@ -143970,11 +143920,11 @@ var makeWecomAppAdapter = (deps) => {
143970
143920
  }
143971
143921
  };
143972
143922
  },
143973
- sendText: async (binding, text3, options) => {
143923
+ sendText: async (binding, text4, options) => {
143974
143924
  if (options?.targetKind === "group") {
143975
143925
  throw new Error("wecom-app can only deliver to a user; group targets are not supported.");
143976
143926
  }
143977
- await apiFor(binding).sendText({ userId: binding.chatId, content: text3 });
143927
+ await apiFor(binding).sendText({ userId: binding.chatId, content: text4 });
143978
143928
  },
143979
143929
  sendImage: (binding, image2) => sendMedia(binding, "image", image2),
143980
143930
  sendFile: (binding, file) => sendMedia(binding, "file", file),
@@ -143991,7 +143941,7 @@ var makeWecomAppAdapter = (deps) => {
143991
143941
  await api.sendText({ userId: binding.chatId, content: numberedApprovalText(request) });
143992
143942
  return null;
143993
143943
  },
143994
- answerByText: (_binding, text3, options) => answerByNumber(text3, options)
143944
+ answerByText: (_binding, text4, options) => answerByNumber(text4, options)
143995
143945
  };
143996
143946
  };
143997
143947
 
@@ -144085,7 +144035,7 @@ var imPlugin = definePlugin({
144085
144035
  const failures = makeFailureNotices(core);
144086
144036
  const replyAnchors = makeReplyAnchors(core.host);
144087
144037
  const replyCards = makeReplyCards(core, failures, replyAnchors);
144088
- const teams = makeTeamRuns(core, { clearWorking: acknowledgements.clearWorking });
144038
+ const teams = makeTeamGoals(core);
144089
144039
  const notifications = makeNotifications(core, {
144090
144040
  clearWorking: acknowledgements.clearWorking,
144091
144041
  replyCards,
@@ -144114,10 +144064,9 @@ var imPlugin = definePlugin({
144114
144064
  const panelWiring = makePanelWiring(core, {
144115
144065
  enqueueForChat: chatQueue.enqueueForChat,
144116
144066
  sessions,
144117
- teams,
144118
144067
  modelPlan,
144119
144068
  rows: projectRows,
144120
- handleCommand: (binding, text3, teamChoices) => commands.handleCommand(binding, text3, teamChoices)
144069
+ handleCommand: (binding, text4) => commands.handleCommand(binding, text4)
144121
144070
  });
144122
144071
  const chatSetup = makeChatSetup(core, {
144123
144072
  rows: projectRows,
@@ -144129,6 +144078,7 @@ var imPlugin = definePlugin({
144129
144078
  sessions,
144130
144079
  modelPlan,
144131
144080
  chatSetup,
144081
+ teams,
144132
144082
  openPanel: (chatKey, reply) => panelWiring.panel.open(chatKey, reply)
144133
144083
  });
144134
144084
  const inbound = makeInbound(core, {