oasis_test_v2 2.2.121 → 2.2.123

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.
Files changed (2) hide show
  1. package/dist/index.js +967 -223
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1634,6 +1634,165 @@ var init_todos = __esm({
1634
1634
  }
1635
1635
  });
1636
1636
 
1637
+ // ../contract/src/overlap.ts
1638
+ function overlapCandidateId(c5) {
1639
+ return c5.kind === "todo" ? c5.todoId : c5.kind === "workorder" ? c5.workorderId : c5.delegationId;
1640
+ }
1641
+ function overlapTokens(text7) {
1642
+ const out = /* @__PURE__ */ new Set();
1643
+ const norm = text7.normalize("NFKC").toLowerCase();
1644
+ let run = "";
1645
+ let word = "";
1646
+ const flushRun = () => {
1647
+ if (run.length === 1) out.add(run);
1648
+ for (let i5 = 0; i5 + 1 < run.length; i5++) out.add(run.slice(i5, i5 + 2));
1649
+ run = "";
1650
+ };
1651
+ const flushWord = () => {
1652
+ if (word.length >= 2) out.add(word);
1653
+ word = "";
1654
+ };
1655
+ for (const ch of norm) {
1656
+ if (isCjk(ch)) {
1657
+ flushWord();
1658
+ run += ch;
1659
+ continue;
1660
+ }
1661
+ flushRun();
1662
+ if (/[\p{L}\p{N}]/u.test(ch)) word += ch;
1663
+ else flushWord();
1664
+ }
1665
+ flushRun();
1666
+ flushWord();
1667
+ for (const t of [...out]) if (STOP_TOKENS.has(t)) out.delete(t);
1668
+ return out;
1669
+ }
1670
+ function overlapSimilarity(a5, b6) {
1671
+ if (a5.size === 0 || b6.size === 0) return 0;
1672
+ let shared = 0;
1673
+ for (const t of a5) if (b6.has(t)) shared++;
1674
+ return shared / Math.sqrt(a5.size * b6.size);
1675
+ }
1676
+ function overlapScore(query, title, body2) {
1677
+ const byTitle = overlapSimilarity(query, overlapTokens(title));
1678
+ const byAll = body2 ? overlapSimilarity(query, overlapTokens(`${title}
1679
+ ${body2}`)) : byTitle;
1680
+ return Math.round(Math.max(byTitle, byAll) * 1e3) / 1e3;
1681
+ }
1682
+ function monthDay(dayOrIso, timeZone) {
1683
+ let day = dayOrIso.slice(0, 10);
1684
+ if (dayOrIso.length > 10) {
1685
+ try {
1686
+ day = new Intl.DateTimeFormat("sv-SE", { timeZone: timeZone ?? "UTC", year: "numeric", month: "2-digit", day: "2-digit" }).format(new Date(dayOrIso));
1687
+ } catch {
1688
+ }
1689
+ }
1690
+ const [, m4, d5] = day.split("-");
1691
+ return `${Number(m4)} \u6708 ${Number(d5)} \u65E5`;
1692
+ }
1693
+ function formatOverlapCandidate(c5, timeZone) {
1694
+ const phase = c5.phase === "active" ? "\u5728\u505A" : "\u505A\u5B8C";
1695
+ if (c5.kind === "todo") {
1696
+ const people = c5.creatorActorId === c5.assigneeActorId ? who(c5.assigneeName, c5.assigneeActorId) : `${who(c5.creatorName, c5.creatorActorId)}\u2192${who(c5.assigneeName, c5.assigneeActorId)}`;
1697
+ const bits2 = [`${phase} \u5F85\u529E ${c5.todoId}`, `${people}\u300C${c5.title}\u300D`];
1698
+ if (c5.phase === "active" && c5.dueDate) bits2.push(`\u622A\u6B62 ${monthDay(c5.dueDate)}`);
1699
+ if (c5.phase === "done" && c5.doneAt) bits2.push(`${monthDay(c5.doneAt, timeZone)}\u5B8C\u6210`);
1700
+ if (c5.phase === "done") bits2.push(c5.result ? `\u7ED3\u679C\u5728\u54EA\uFF1A${c5.result}` : "\u7ED3\u679C\u5728\u54EA\uFF1A\uFF08\u6CA1\u8BB0\uFF09");
1701
+ if (c5.sourceChatSessionId) bits2.push(`\u51FA\u5904\u5BF9\u8BDD ${c5.sourceChatSessionId}`);
1702
+ return ` ${bits2.join(" ")}`;
1703
+ }
1704
+ if (c5.kind === "workorder") {
1705
+ const bits2 = [`${phase} \u5DE5\u5355 ${c5.workorderId}`, `${c5.initiatorActorId || c5.initiatorName ? who(c5.initiatorName, c5.initiatorActorId) : ""}\u300C${c5.title}\u300D`];
1706
+ if (c5.phase === "active" && c5.dueDate) bits2.push(`\u622A\u6B62 ${monthDay(c5.dueDate)}`);
1707
+ if (c5.phase === "done" && c5.endedAt) bits2.push(`${monthDay(c5.endedAt, timeZone)}\u7ED3\u675F`);
1708
+ if (c5.deliverableCount !== void 0) bits2.push(`\u4EA4\u4ED8\u7269 ${c5.deliverableCount} \u4E2A`);
1709
+ return ` ${bits2.join(" ")}`;
1710
+ }
1711
+ const bits = [
1712
+ `${phase} \u59D4\u6D3E ${c5.delegationId}\uFF08\u5B50\u4F1A\u8BDD ${c5.childSessionId}\uFF0C\u51FA\u81EA\u5BF9\u8BDD ${c5.parentSessionId}\uFF09`,
1713
+ `${who(c5.delegatorName, c5.delegatorActorId)}\u2192${who(c5.expertName, c5.expertActorId)}\u300C${c5.title}\u300D`
1714
+ ];
1715
+ if (c5.phase === "done" && c5.settledAt) bits.push(`${monthDay(c5.settledAt, timeZone)}\u4EA4\u56DE`);
1716
+ bits.push(`\u4EA7\u51FA ${c5.artifactCount} \u4E2A`);
1717
+ return ` ${bits.join(" ")}`;
1718
+ }
1719
+ function formatOverlapLines(r5, timeZone) {
1720
+ const all2 = [...r5.active, ...r5.done];
1721
+ if (all2.length === 0) return [];
1722
+ return [OVERLAP_HEADING, ...all2.map((c5) => formatOverlapCandidate(c5, timeZone)), OVERLAP_LOOKUP_HINT, OVERLAP_HANDLING_HINT];
1723
+ }
1724
+ var OVERLAP_ACTIONS, STOP_TOKENS, isCjk, OVERLAP_HEADING, OVERLAP_LOOKUP_HINT, OVERLAP_HANDLING_HINT, who;
1725
+ var init_overlap = __esm({
1726
+ "../contract/src/overlap.ts"() {
1727
+ "use strict";
1728
+ OVERLAP_ACTIONS = ["todo-add", "delegate", "create-workorder", "run-playbook"];
1729
+ STOP_TOKENS = /* @__PURE__ */ new Set([
1730
+ "\u4E00\u4E0B",
1731
+ "\u5E2E\u6211",
1732
+ "\u6211\u4EEC",
1733
+ "\u4F60\u4EEC",
1734
+ "\u4ED6\u4EEC",
1735
+ "\u8FD9\u4E2A",
1736
+ "\u90A3\u4E2A",
1737
+ "\u8FD9\u4E9B",
1738
+ "\u90A3\u4E9B",
1739
+ "\u4E00\u4E2A",
1740
+ "\u4E00\u4EFD",
1741
+ "\u4E00\u7248",
1742
+ "\u4E00\u4E9B",
1743
+ "\u8FDB\u884C",
1744
+ "\u76F8\u5173",
1745
+ "\u9700\u8981",
1746
+ "\u5DF2\u7ECF",
1747
+ "\u8FD8\u662F",
1748
+ "\u7136\u540E",
1749
+ "\u4EE5\u53CA",
1750
+ "\u6216\u8005",
1751
+ "\u5982\u679C",
1752
+ "\u53EF\u4EE5",
1753
+ "\u8981\u6C42",
1754
+ "\u95EE\u9898",
1755
+ "\u4E8B\u60C5",
1756
+ "\u5DE5\u4F5C",
1757
+ "\u5904\u7406",
1758
+ "\u5B8C\u6210",
1759
+ "\u770B\u770B",
1760
+ "\u6574\u7406",
1761
+ "\u51C6\u5907",
1762
+ "\u4ECA\u5929",
1763
+ "\u660E\u5929",
1764
+ "\u672C\u5468",
1765
+ "\u4E0B\u5468",
1766
+ "\u5468\u4E00",
1767
+ "\u5468\u4E8C",
1768
+ "\u5468\u4E09",
1769
+ "\u5468\u56DB",
1770
+ "\u5468\u4E94",
1771
+ "\u5468\u516D",
1772
+ "\u5468\u65E5",
1773
+ "\u4E4B\u524D",
1774
+ "\u4E4B\u540E",
1775
+ "\u4EE5\u524D",
1776
+ "\u622A\u6B62",
1777
+ "the",
1778
+ "and",
1779
+ "for",
1780
+ "with",
1781
+ "from",
1782
+ "this",
1783
+ "that",
1784
+ "into",
1785
+ "todo",
1786
+ "task"
1787
+ ]);
1788
+ isCjk = (ch) => /[㐀-鿿豈-﫿]/u.test(ch);
1789
+ OVERLAP_HEADING = "\u76F8\u8FD1\u7684\u4E8B\u9879\uFF08\u7CFB\u7EDF\u7C97\u7B5B\uFF0C\u672A\u786E\u8BA4\uFF0C\u8BF7\u7528 id \u67E5\u8BE6\u60C5\u540E\u5224\u65AD\uFF09\uFF1A";
1790
+ OVERLAP_LOOKUP_HINT = "\u67E5\u8BE6\u60C5\uFF1A\u5F85\u529E oasis todo show <\u5F85\u529Eid>\uFF1B\u5DE5\u5355 oasis workorder <\u5DE5\u5355id>\uFF1B\u59D4\u6D3E oasis delegate --status <\u59D4\u6D3Eid>\uFF08\u522B\u4EBA\u5BF9\u8BDD\u91CC\u6D3E\u7684\u4E5F\u80FD\u67E5\u6458\u8981\uFF09";
1791
+ OVERLAP_HANDLING_HINT = "\u600E\u4E48\u7528\uFF1A\u9010\u6761\u67E5\u5B8C\u518D\u5224\u65AD\u662F\u4E0D\u662F\u540C\u4E00\u4EF6\u4E8B\uFF1B\u786E\u5B9E\u76F8\u5173\u624D\u544A\u8BC9\u7528\u6237\uFF0C\u4E0D\u76F8\u5173\u4E00\u4E2A\u5B57\u4E0D\u63D0\u3002\u5728\u505A\u7684\u5EFA\u8BAE\u7528\u6237\u5148\u95EE\u95EE\u5BF9\u65B9\uFF0C\u770B\u5408\u5E76\u8FD8\u662F\u5206\u5DE5\uFF1B\u505A\u5B8C\u7684\u628A\u7ED3\u679C\u7ED9\u7528\u6237\uFF0C\u95EE\u80FD\u4E0D\u80FD\u76F4\u63A5\u7528\u3002\u4E0D\u66FF\u7528\u6237\u5408\u5E76\u3001\u53D6\u6D88\u6216\u6539\u6D3E\u3002";
1792
+ who = (name, id) => name ?? id ?? "\uFF08\u672A\u77E5\uFF09";
1793
+ }
1794
+ });
1795
+
1637
1796
  // ../contract/src/credential-gap.ts
1638
1797
  function buildCredentialGapDescription(opts) {
1639
1798
  const { key: key2, scope: scope2, project, desc } = opts;
@@ -2140,6 +2299,21 @@ function trimRoundSummariesForReturn(summaries, recentRounds = DELEGATION_RETURN
2140
2299
  return { round: summary.round, text: firstLine3, truncated: true };
2141
2300
  });
2142
2301
  }
2302
+ function delegationOverlapRowOf(record10, createdText) {
2303
+ return {
2304
+ id: record10.id,
2305
+ childSessionId: record10.childSessionId,
2306
+ parentSessionId: record10.parentSessionId,
2307
+ expertActorId: record10.expertActorId,
2308
+ state: record10.state === "done" ? "done" : "running",
2309
+ taskText: createdText?.trim() || record10.taskDigest || "",
2310
+ ...record10.taskDigest ? { taskDigest: record10.taskDigest } : {},
2311
+ ...record10.label ? { label: record10.label } : {},
2312
+ createdAt: record10.createdAt,
2313
+ ...record10.settledAt ? { settledAt: record10.settledAt } : {},
2314
+ artifactCount: collectDelegationArtifacts(record10.roundSummaries).length
2315
+ };
2316
+ }
2143
2317
  function collectDelegationArtifacts(roundSummaries) {
2144
2318
  const out = [];
2145
2319
  for (const round of roundSummaries) {
@@ -2701,6 +2875,7 @@ var init_src = __esm({
2701
2875
  init_variable_name();
2702
2876
  init_time_zone();
2703
2877
  init_todos();
2878
+ init_overlap();
2704
2879
  init_credential_gap();
2705
2880
  init_views();
2706
2881
  init_telemetry();
@@ -21052,13 +21227,13 @@ async function persistFeishuUserTokens(store, actorId, data, nowMs) {
21052
21227
  const { credentials: credentials2 } = parseFeishuTokenResponse(data, nowMs);
21053
21228
  await persistRefreshedCredentials(store, new FeishuConnector(), actorId, credentials2);
21054
21229
  }
21055
- async function persistFeishuUserAuthorization(store, actorId, data, nowMs, who = {}) {
21230
+ async function persistFeishuUserAuthorization(store, actorId, data, nowMs, who2 = {}) {
21056
21231
  await persistFeishuUserTokens(store, actorId, data, nowMs);
21057
21232
  const scope2 = actorId ? { scope: "personal", actorId } : { scope: "global" };
21058
21233
  const put3 = (key2, value2) => value2 ? store.putVariable({ key: key2, value: value2, ...scope2, connectorId: "feishu", encrypted: false }) : Promise.resolve();
21059
- await put3(FEISHU_USER_OPEN_ID_VAR, who.openId);
21060
- await put3("FEISHU_USER_NAME", who.userName);
21061
- await put3(FEISHU_AUTHORIZED_BY_VAR, who.authorizedBy);
21234
+ await put3(FEISHU_USER_OPEN_ID_VAR, who2.openId);
21235
+ await put3("FEISHU_USER_NAME", who2.userName);
21236
+ await put3(FEISHU_AUTHORIZED_BY_VAR, who2.authorizedBy);
21062
21237
  await store.deleteVariable(FEISHU_USER_AUTH_INVALID_VAR, actorId);
21063
21238
  }
21064
21239
  async function readFeishuUserAuthInvalid(store, actorId) {
@@ -25000,15 +25175,15 @@ function createFeishuReauth(deps) {
25000
25175
  return appId && appSecret ? { appId, appSecret } : null;
25001
25176
  };
25002
25177
  const settle = async (claims, store, data, sel, sendAsUserRequested, appId) => {
25003
- const who = await (deps.identity ?? fetchFeishuUserIdentity)(String(data["access_token"] ?? ""));
25004
- if (!who.openId) {
25178
+ const who2 = await (deps.identity ?? fetchFeishuUserIdentity)(String(data["access_token"] ?? ""));
25179
+ if (!who2.openId) {
25005
25180
  return { state: "error", message: "\u6388\u6743\u5B8C\u6210\u4E86\uFF0C\u4F46\u6CA1\u80FD\u5411\u98DE\u4E66\u786E\u8BA4\u6388\u6743\u4EBA\u662F\u8C01\uFF0C\u672C\u6B21\u6388\u6743\u672A\u4FDD\u5B58\u3002\u8BF7\u7A0D\u540E\u91CD\u65B0\u70B9\u94FE\u63A5\u518D\u8BD5\u3002" };
25006
25181
  }
25007
- if (who.openId !== claims.subject) {
25008
- await deps.onRejected?.(claims, who).catch((e5) => warn(`onRejected: ${String(e5)}`));
25182
+ if (who2.openId !== claims.subject) {
25183
+ await deps.onRejected?.(claims, who2).catch((e5) => warn(`onRejected: ${String(e5)}`));
25009
25184
  return {
25010
25185
  state: "rejected",
25011
- message: `\u8FD9\u4E2A\u94FE\u63A5\u53EA\u80FD\u7531\u539F\u6388\u6743\u4EBA\u672C\u4EBA\u4F7F\u7528\u3002\u4F60${who.name ? `\uFF08${who.name}\uFF09` : ""}\u4E0D\u662F\u539F\u6388\u6743\u4EBA\uFF0C\u672C\u6B21\u6388\u6743\u672A\u4FDD\u5B58\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3002`
25186
+ message: `\u8FD9\u4E2A\u94FE\u63A5\u53EA\u80FD\u7531\u539F\u6388\u6743\u4EBA\u672C\u4EBA\u4F7F\u7528\u3002\u4F60${who2.name ? `\uFF08${who2.name}\uFF09` : ""}\u4E0D\u662F\u539F\u6388\u6743\u4EBA\uFF0C\u672C\u6B21\u6388\u6743\u672A\u4FDD\u5B58\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3002`
25012
25187
  };
25013
25188
  }
25014
25189
  const supplement = await withConnectorCredentialLock("feishu", claims.actorId, async () => {
@@ -25050,8 +25225,8 @@ function createFeishuReauth(deps) {
25050
25225
  }
25051
25226
  if (!kept) {
25052
25227
  await persistFeishuUserAuthorization(store, claims.actorId, data, now(), {
25053
- openId: who.openId,
25054
- ...who.name ? { userName: who.name } : {},
25228
+ openId: who2.openId,
25229
+ ...who2.name ? { userName: who2.name } : {},
25055
25230
  ...pending2?.applicant ? { authorizedBy: pending2.applicant } : {}
25056
25231
  });
25057
25232
  await store.putVariable({
@@ -25071,7 +25246,7 @@ function createFeishuReauth(deps) {
25071
25246
  }
25072
25247
  return outcome === null ? null : { outcome, kept };
25073
25248
  });
25074
- const userName = who.name ? { userName: who.name } : {};
25249
+ const userName = who2.name ? { userName: who2.name } : {};
25075
25250
  if (supplement && supplement.outcome !== "complete") {
25076
25251
  const saved = supplement.kept ? "\u4E3A\u4E0D\u5F71\u54CD\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3001\u8FD9\u6B21\u6388\u6743\u6CA1\u6709\u4FDD\u5B58\uFF08\u98DE\u4E66\u8FD9\u6B21\u7ED9\u7684\u6388\u6743\u4E0D\u5305\u542B\u4F60\u73B0\u6709\u6388\u6743\u7684\u5168\u90E8\u6743\u9650\uFF09\u3002" : "\u6388\u6743\u5DF2\u4FDD\u5B58\u3002";
25077
25252
  const message = {
@@ -25081,8 +25256,8 @@ function createFeishuReauth(deps) {
25081
25256
  }[supplement.outcome];
25082
25257
  return { state: "incomplete", ...userName, message };
25083
25258
  }
25084
- await deps.onRestored?.(claims, { openId: who.openId, ...userName }).catch((e5) => warn(`onRestored: ${String(e5)}`));
25085
- return { state: "restored", ...who.name ? { userName: who.name } : {} };
25259
+ await deps.onRestored?.(claims, { openId: who2.openId, ...userName }).catch((e5) => warn(`onRestored: ${String(e5)}`));
25260
+ return { state: "restored", ...who2.name ? { userName: who2.name } : {} };
25086
25261
  };
25087
25262
  const watch = async (deviceCode, entry, ctx) => {
25088
25263
  while (now() < entry.expiresAtMs) {
@@ -152965,22 +153140,22 @@ function isRoundLimitParked(a5) {
152965
153140
  }
152966
153141
  return false;
152967
153142
  }
152968
- function latestMentionSeq(model, a5, who) {
153143
+ function latestMentionSeq(model, a5, who2) {
152969
153144
  const rootSeq = model.annotationSeq.get(a5.id) ?? 0;
152970
- let seq = a5.mentions.includes(who) ? rootSeq : -1;
153145
+ let seq = a5.mentions.includes(who2) ? rootSeq : -1;
152971
153146
  for (const t of a5.thread) {
152972
- if ((t.mentions ?? []).includes(who) && (t.seq ?? rootSeq) > seq) seq = t.seq ?? rootSeq;
153147
+ if ((t.mentions ?? []).includes(who2) && (t.seq ?? rootSeq) > seq) seq = t.seq ?? rootSeq;
152973
153148
  }
152974
153149
  return seq;
152975
153150
  }
152976
- function repliedAfter(a5, who, sinceSeq) {
152977
- return a5.thread.some((t) => t.author === who && (t.seq ?? -1) > sinceSeq);
153151
+ function repliedAfter(a5, who2, sinceSeq) {
153152
+ return a5.thread.some((t) => t.author === who2 && (t.seq ?? -1) > sinceSeq);
152978
153153
  }
152979
- function hasUnansweredMention(model, a5, who) {
152980
- const seq = latestMentionSeq(model, a5, who);
153154
+ function hasUnansweredMention(model, a5, who2) {
153155
+ const seq = latestMentionSeq(model, a5, who2);
152981
153156
  if (seq < 0) return false;
152982
153157
  if (seq <= (a5.resolvedAtSeq ?? Number.NEGATIVE_INFINITY)) return false;
152983
- return !repliedAfter(a5, who, seq);
153158
+ return !repliedAfter(a5, who2, seq);
152984
153159
  }
152985
153160
  function defaultRecipientOf(model, a5, owner) {
152986
153161
  if (a5.mentions.length === 1) {
@@ -152990,10 +153165,10 @@ function defaultRecipientOf(model, a5, owner) {
152990
153165
  }
152991
153166
  return owner;
152992
153167
  }
152993
- function lastPostSeqOf(model, a5, who) {
153168
+ function lastPostSeqOf(model, a5, who2) {
152994
153169
  const rootSeq = model.annotationSeq.get(a5.id) ?? 0;
152995
- let seq = a5.author === who ? rootSeq : Number.NEGATIVE_INFINITY;
152996
- for (const t of a5.thread) if (t.author === who && (t.seq ?? rootSeq) > seq) seq = t.seq ?? rootSeq;
153170
+ let seq = a5.author === who2 ? rootSeq : Number.NEGATIVE_INFINITY;
153171
+ for (const t of a5.thread) if (t.author === who2 && (t.seq ?? rootSeq) > seq) seq = t.seq ?? rootSeq;
152997
153172
  return seq;
152998
153173
  }
152999
153174
  function owesReplyOn(model, a5, recipient, owner) {
@@ -154435,11 +154610,11 @@ function anomalyLabel(a5) {
154435
154610
  }
154436
154611
  }
154437
154612
  function renderLedgerMarkdown(ledger, opts = {}) {
154438
- const who = (id) => id === void 0 ? "\uFF08\u672A\u6307\u5B9A\uFF09" : opts.actorLabel?.(id) ?? id;
154613
+ const who2 = (id) => id === void 0 ? "\uFF08\u672A\u6307\u5B9A\uFF09" : opts.actorLabel?.(id) ?? id;
154439
154614
  const out = [];
154440
154615
  out.push(`## \u5DE5\u5355 ${ledger.workspace}${ledger.title ? ` \xB7 ${ledger.title}` : ""}`);
154441
154616
  if (ledger.goal) out.push(`\u76EE\u6807\uFF1A${ledger.goal}`);
154442
- out.push(`\u63D0\u5355\u4EBA ${who(ledger.owner)} | \u7BA1\u7406\u8005 ${who(ledger.manager)}`);
154617
+ out.push(`\u63D0\u5355\u4EBA ${who2(ledger.owner)} | \u7BA1\u7406\u8005 ${who2(ledger.manager)}`);
154443
154618
  const span = ledger.startedAt && ledger.endedAt ? ` | ${ledger.startedAt} \u2192 ${ledger.endedAt}` : "";
154444
154619
  out.push(`\u4EA7\u7269 ${ledger.artifactCount} \u4EFD | \u672A\u89E3\u7F3A\u53E3 ${ledger.unresolvedGapCount} | \u672A\u51B3\u6279\u6CE8 ${ledger.openAnnotationCount}${span}`);
154445
154620
  if (ledger.briefId) out.push(`\u5DE5\u5355\u6B63\u6587\uFF1A\`oasis content ${ledger.briefId}\``);
@@ -154449,20 +154624,20 @@ function renderLedgerMarkdown(ledger, opts = {}) {
154449
154624
  out.push(``, `### \u8282\u70B9\uFF08\u62D3\u6251\u5E8F\uFF09`);
154450
154625
  ledger.nodes.forEach((n3, i5) => {
154451
154626
  out.push(``);
154452
- out.push(`[${i5 + 1}] ${n3.id} type=${n3.type} owner=${who(n3.owner)}${n3.lifecycle !== "active" ? ` ${n3.lifecycle}` : ""}`);
154627
+ out.push(`[${i5 + 1}] ${n3.id} type=${n3.type} owner=${who2(n3.owner)}${n3.lifecycle !== "active" ? ` ${n3.lifecycle}` : ""}`);
154453
154628
  if (n3.title) out.push(` ${n3.title}`);
154454
154629
  const anomalies = n3.anomalies.length === 0 ? "0" : `${n3.anomalies.length}\uFF08${n3.anomalies.map(anomalyLabel).join("\u3001")}\uFF09`;
154455
154630
  out.push(
154456
154631
  ` head=${shortRev(n3.head)} \u5DF2\u4EA4\u4ED8=${shortRev(n3.concludedHead)} \u7248\u672C ${n3.revisionCount} \u6253\u56DE ${n3.rejectedRounds} \u5F02\u5E38\u8BB0\u5F55 ${anomalies}`
154457
154632
  );
154458
154633
  for (const u of n3.upstreams) out.push(` \u4E0A\u6E38 ${u.to}@${shortRev(u.pinned)}${u.required ? " [required]" : ""}`);
154459
- for (const g6 of n3.unresolvedGaps) out.push(` \u672A\u89E3\u7F3A\u53E3 by ${who(g6.by)}\uFF1A${g6.description}`);
154634
+ for (const g6 of n3.unresolvedGaps) out.push(` \u672A\u89E3\u7F3A\u53E3 by ${who2(g6.by)}\uFF1A${g6.description}`);
154460
154635
  for (const a5 of n3.openAnnotations) {
154461
- out.push(` \u672A\u51B3\u6279\u6CE8 [${a5.kind}] by ${who(a5.author)}${a5.stagedResolution ? `\uFF08\u5F85\u88C1\u51B3\uFF1A${a5.stagedResolution}\uFF09` : ""}\uFF1A${a5.body}`);
154636
+ out.push(` \u672A\u51B3\u6279\u6CE8 [${a5.kind}] by ${who2(a5.author)}${a5.stagedResolution ? `\uFF08\u5F85\u88C1\u51B3\uFF1A${a5.stagedResolution}\uFF09` : ""}\uFF1A${a5.body}`);
154462
154637
  }
154463
154638
  for (const r5 of n3.reviews) {
154464
154639
  out.push(
154465
- ` \u7968 ${shortRev(r5.revisionId)} ${r5.verdict} ${r5.at} by ${who(r5.author)}` + (r5.hasNote ? `\uFF08\u8BC4\u8BED \`oasis content ${r5.noteRef}\`\uFF09` : "\uFF08\u65E0\u8BC4\u8BED\uFF09")
154640
+ ` \u7968 ${shortRev(r5.revisionId)} ${r5.verdict} ${r5.at} by ${who2(r5.author)}` + (r5.hasNote ? `\uFF08\u8BC4\u8BED \`oasis content ${r5.noteRef}\`\uFF09` : "\uFF08\u65E0\u8BC4\u8BED\uFF09")
154466
154641
  );
154467
154642
  }
154468
154643
  for (const r5 of n3.revisions) out.push(` reason ${shortRev(r5.id)}\uFF1A${r5.reason}`);
@@ -154934,7 +155109,7 @@ async function assembleContext(args) {
154934
155109
  const detail = [];
154935
155110
  for (const r5 of queued) {
154936
155111
  const info = queuedParts.find((q4) => q4.revisionId === r5.id);
154937
- const who = r5.author === artifact.owner ? "\u4F60\u81EA\u5DF1\u4E0A\u4E00\u8F6E" : actorLabel(r5.author);
155112
+ const who2 = r5.author === artifact.owner ? "\u4F60\u81EA\u5DF1\u4E0A\u4E00\u8F6E" : actorLabel(r5.author);
154938
155113
  const baseC = await contentMapOf(r5.base ? model.revisions.get(r5.base) ?? null : null);
154939
155114
  const newC = await contentMapOf(r5);
154940
155115
  const dir = info?.dir ?? `competing/${slug3(r5.id.slice(9, 17))}`;
@@ -154951,7 +155126,7 @@ ${manifestDiff(baseC, newC)}
154951
155126
  where = `\u5185\u5BB9\u89C1 \`${dir}/\`\uFF1B${queueHandler.diffFallback({ artifactId, contentRef: r5.contentRef, contentKind: r5.contentKind })}`;
154952
155127
  }
154953
155128
  detail.push(
154954
- `- \`${r5.id.slice(9, 17)}\`\uFF08${who}${r5.part ? ` \xB7 \u90E8\u4EF6 ${r5.part}` : " \xB7 \u7ADE\u4E89\u7248"}\uFF09\uFF1A${r5.reason}
155129
+ `- \`${r5.id.slice(9, 17)}\`\uFF08${who2}${r5.part ? ` \xB7 \u90E8\u4EF6 ${r5.part}` : " \xB7 \u7ADE\u4E89\u7248"}\uFF09\uFF1A${r5.reason}
154955
155130
  ${where}`
154956
155131
  );
154957
155132
  }
@@ -161711,7 +161886,7 @@ var init_kernel_bridge = __esm({
161711
161886
  const gap = gapId ? gapById(this.model, gapId) : null;
161712
161887
  const hit = esc2?.resolved ? { kind: "escalation", id: esc2.escalationId, ...esc2.resolvedBy ? { resolvedBy: esc2.resolvedBy } : {}, ...esc2.resolvedAt ? { resolvedAt: esc2.resolvedAt } : {} } : gap?.resolved ? { kind: "gap", id: gap.gapId, ...gap.resolvedBy ? { resolvedBy: gap.resolvedBy } : {}, ...gap.resolvedAt ? { resolvedAt: gap.resolvedAt } : {} } : null;
161713
161888
  if (!hit) continue;
161714
- const who = hit.resolvedBy ?? "\u7CFB\u7EDF";
161889
+ const who2 = hit.resolvedBy ?? "\u7CFB\u7EDF";
161715
161890
  const when = hit.resolvedAt ?? "\u66F4\u65E9";
161716
161891
  out.push({
161717
161892
  draftId,
@@ -161720,7 +161895,7 @@ var init_kernel_bridge = __esm({
161720
161895
  proposedBy: card2.proposedBy,
161721
161896
  origin: card2.origin ?? null,
161722
161897
  target: hit,
161723
- reason: `\u5DF2\u5931\u6548\uFF1A\u8FD9\u6761${hit.kind === "escalation" ? "\u4E0A\u62A5" : "\u7F3A\u53E3"}\uFF08${hit.id}\uFF09\u5DF2\u7531 ${who} \u4E8E ${when} \u5173\u95ED\uFF0C\u65E0\u9700\u518D\u5904\u7F6E\u3002`
161898
+ reason: `\u5DF2\u5931\u6548\uFF1A\u8FD9\u6761${hit.kind === "escalation" ? "\u4E0A\u62A5" : "\u7F3A\u53E3"}\uFF08${hit.id}\uFF09\u5DF2\u7531 ${who2} \u4E8E ${when} \u5173\u95ED\uFF0C\u65E0\u9700\u518D\u5904\u7F6E\u3002`
161724
161899
  });
161725
161900
  }
161726
161901
  return out;
@@ -183871,11 +184046,11 @@ function nodeReviewerReceiptLines(nodes5) {
183871
184046
  return [
183872
184047
  "\u5404\u8282\u70B9\u6700\u7EC8\u751F\u6548\u7684\u5BA1\u6838\u4EBA\uFF08\u300C\u6307\u5B9A\u300D= plan \u91CC reviewers \u7ED9\u7684\u4EBA\uFF0C\u5DF2\u66FF\u6362\u8BE5\u7C7B\u578B\u7684\u9ED8\u8BA4\u5BA1\u6838\u4EBA\uFF1B\u300C\u7C7B\u578B\u9ED8\u8BA4\u300D= \u6CA1\u6307\u5B9A\u3001\u6309\u8282\u70B9\u7C7B\u578B\u81EA\u5E26\uFF1B\u8DDF\u7528\u6237\u8BF4\u5BA1\u6838\u4EBA\u65F6\u4EE5\u8FD9\u91CC\u4E3A\u51C6\uFF09\uFF1A",
183873
184048
  ...nodes5.map((node2) => {
183874
- const who = (node2.reviewers ?? []).map((r5) => {
184049
+ const who2 = (node2.reviewers ?? []).map((r5) => {
183875
184050
  const name = r5.actor.name && r5.actor.name !== r5.actor.id ? `${r5.actor.name}\uFF08${r5.actor.id}\uFF0C` : `${r5.actor.id}\uFF08`;
183876
184051
  return `${name}${REVIEWER_SOURCE_LABEL[r5.source]}\uFF09`;
183877
184052
  });
183878
- return ` ${node2.type}\u300C${node2.label}\u300D\uFF1A${who.length > 0 ? who.join("\u3001") : "\u65E0\u5BA1\u6838\u4EBA"}`;
184053
+ return ` ${node2.type}\u300C${node2.label}\u300D\uFF1A${who2.length > 0 ? who2.join("\u3001") : "\u65E0\u5BA1\u6838\u4EBA"}`;
183879
184054
  })
183880
184055
  ];
183881
184056
  }
@@ -211478,6 +211653,53 @@ ${inboundBundle.paths.map((path50) => `- ${path50}`).join("\n")}` : text7,
211478
211653
  ...record10.settledAt ? { settledAt: record10.settledAt } : {}
211479
211654
  };
211480
211655
  }
211656
+ /**
211657
+ * `GET /api/delegations/:id/summary`(ADR 0640 第二批)——**本公司任何人**按 id 读一条委派的**摘要**:
211658
+ * 任务书、状态、专家、各轮小结、产出文件名、派活对话 id、子会话 id、派活人。
211659
+ *
211660
+ * 与 {@link get} 的分工:`get` 是协调者(派活那段对话)的工作口,`--status` / `--follow-up` 都靠它,**原样不动**;
211661
+ * 这条是给「别人对话里派出的委派」的只读口——防重叠比对的候选里带着委派 id,拿到了要能查。
211662
+ * - **不返回子会话的完整过程**(专家干活的原始记录,量大也用不上):任务书只取子会话第一轮那条输入,其余消息一条不读。
211663
+ * - 本公司:store 按调用者的公司取,别家公司的 id 在这里就是不存在(404,不区分「没有」与「不是你家的」)。
211664
+ * - 列表接口**不放开**:只能拿已知的 id 来读。
211665
+ */
211666
+ async summary(delegationId, caller) {
211667
+ this.assertEnabled();
211668
+ const store = await this.options.resolveStore(caller.companyId);
211669
+ const record10 = await store.get(delegationId);
211670
+ if (!record10) throw new DelegationError(404, "DELEGATION_NOT_FOUND", `\u672C\u516C\u53F8\u6CA1\u6709 id \u4E3A ${delegationId} \u7684\u59D4\u6D3E\u3002`);
211671
+ const chatStore = await this.options.resolveChatSessions(caller.companyId).catch(() => null);
211672
+ const parent = chatStore ? await chatStore.getSession(record10.parentSessionId).catch(() => null) : null;
211673
+ if (parent?.companyId && caller.companyId && parent.companyId !== caller.companyId) {
211674
+ throw new DelegationError(404, "DELEGATION_NOT_FOUND", `\u672C\u516C\u53F8\u6CA1\u6709 id \u4E3A ${delegationId} \u7684\u59D4\u6D3E\u3002`);
211675
+ }
211676
+ const actors = await this.options.resolveActors(caller.companyId).catch(() => null);
211677
+ const nameOf2 = async (id) => id && actors ? (await actors.getActor(id).catch(() => null))?.name : void 0;
211678
+ const expertName = await nameOf2(record10.expertActorId);
211679
+ const delegator = parent?.humanActorId ?? void 0;
211680
+ const delegatorName = await nameOf2(delegator);
211681
+ const inputId = childRoundMessageIds(record10.childSessionId, 1).inputId;
211682
+ const firstInput = !chatStore ? null : chatStore.getMessage ? await chatStore.getMessage(inputId).catch(() => null) : (await chatStore.listMessages(record10.childSessionId).catch(() => [])).find((m4) => m4.id === inputId) ?? null;
211683
+ const task = firstInput?.sessionId === record10.childSessionId && firstInput.content ? firstInput.content : void 0;
211684
+ return {
211685
+ id: record10.id,
211686
+ parentSessionId: record10.parentSessionId,
211687
+ childSessionId: record10.childSessionId,
211688
+ ...delegator ? { delegatorActorId: delegator } : {},
211689
+ ...delegatorName ? { delegatorName } : {},
211690
+ expertActorId: record10.expertActorId,
211691
+ ...expertName ? { expertName } : {},
211692
+ state: record10.state,
211693
+ ...record10.failureKind ? { failureKind: record10.failureKind } : {},
211694
+ ...record10.label ? { label: record10.label } : {},
211695
+ task: task ?? record10.taskDigest ?? "",
211696
+ ...task ? {} : { taskTruncated: true },
211697
+ rounds: record10.roundSummaries.map((r5) => ({ round: r5.round, at: r5.at, text: r5.text, files: (r5.files ?? []).map((f6) => f6.name) })),
211698
+ artifacts: delegationArtifactsView(record10).map((a5) => a5.name),
211699
+ createdAt: record10.createdAt,
211700
+ ...record10.settledAt ? { settledAt: record10.settledAt } : {}
211701
+ };
211702
+ }
211481
211703
  /**
211482
211704
  * `GET /api/delegations` —— **本父会话**的委派清单(`--list`)。
211483
211705
  *
@@ -211654,6 +211876,13 @@ function delegationRoutes(service) {
211654
211876
  rethrow(error3);
211655
211877
  }
211656
211878
  });
211879
+ router.get("/api/delegations/:id/summary", async (req) => {
211880
+ try {
211881
+ return { status: 200, body: await service.summary(req.params.id, callerOf(req)) };
211882
+ } catch (error3) {
211883
+ rethrow(error3);
211884
+ }
211885
+ });
211657
211886
  router.get("/api/delegations/:id", async (req) => {
211658
211887
  try {
211659
211888
  return { status: 200, body: await service.get(req.params.id, callerOf(req)) };
@@ -211737,6 +211966,12 @@ var init_store2 = __esm({
211737
211966
  async listByParent(parentSessionId, opts) {
211738
211967
  return [...this.rows.values()].filter((r5) => r5.parentSessionId === parentSessionId && (!opts?.state || r5.state === opts.state)).sort((a5, b6) => a5.createdAt === b6.createdAt ? a5.id.localeCompare(b6.id) : a5.createdAt.localeCompare(b6.createdAt)).map((r5) => this.clone(r5));
211739
211968
  }
211969
+ /** 防重叠比对的委派池(ADR 0640 第二批):与 PG 版同一口径——进行中与已交回的,失败的不给;任务书摘要取发起那次的流水。 */
211970
+ async listForOverlap() {
211971
+ const createdText = /* @__PURE__ */ new Map();
211972
+ for (const t of this.touches.values()) if (t.kind === "created") createdText.set(t.delegationId, t.textDigest);
211973
+ return [...this.rows.values()].filter((r5) => r5.state === "running" || r5.state === "done").sort((a5, b6) => a5.createdAt === b6.createdAt ? a5.id.localeCompare(b6.id) : b6.createdAt.localeCompare(a5.createdAt)).map((r5) => delegationOverlapRowOf(this.clone(r5), createdText.get(r5.id)));
211974
+ }
211740
211975
  async patch(id, patch) {
211741
211976
  const current = this.rows.get(id);
211742
211977
  if (!current) return null;
@@ -212048,8 +212283,8 @@ function delegationReturnSource(record10) {
212048
212283
  }
212049
212284
  function delegationReturnText(terminal, opts) {
212050
212285
  const { record: record10 } = terminal;
212051
- const who = terminal.expertName ?? record10.expertActorId;
212052
- const name = record10.label ? `${who}\uFF08${record10.label}\uFF09` : who;
212286
+ const who2 = terminal.expertName ?? record10.expertActorId;
212287
+ const name = record10.label ? `${who2}\uFF08${record10.label}\uFF09` : who2;
212053
212288
  const lastRoundText = record10.roundSummaries[record10.roundSummaries.length - 1]?.text;
212054
212289
  const ending = delegationEnding(record10, {
212055
212290
  movedFiles: opts.movedPaths.length,
@@ -214367,8 +214602,8 @@ async function runView(kernel, oplog, engineStore, blobs, name, artifactId, para
214367
214602
  if (!rev) throw new Error(`\u7248\u672C\u4E0D\u5B58\u5728: ${revisionId}\uFF08\u8BC4\u5BA1\u7968 id \u7684\u524D\u534A\u6BB5\u5E94\u662F revision \u7684 uuid\uFF09`);
214368
214603
  const mine = (model.reviews.get(revisionId) ?? []).filter((v2) => v2.author === author);
214369
214604
  if (mine.length === 0) {
214370
- const who = [...new Set((model.reviews.get(revisionId) ?? []).map((v2) => v2.author))].join("\u3001");
214371
- throw new Error(`${author} \u6CA1\u6709\u5728 ${revisionId} \u4E0A\u6295\u8FC7\u7968${who ? `\uFF08\u8BE5\u7248\u672C\u7684\u6295\u7968\u4EBA\uFF1A${who}\uFF09` : "\uFF08\u8BE5\u7248\u672C\u65E0\u4EBA\u6295\u7968\uFF09"}`);
214605
+ const who2 = [...new Set((model.reviews.get(revisionId) ?? []).map((v2) => v2.author))].join("\u3001");
214606
+ throw new Error(`${author} \u6CA1\u6709\u5728 ${revisionId} \u4E0A\u6295\u8FC7\u7968${who2 ? `\uFF08\u8BE5\u7248\u672C\u7684\u6295\u7968\u4EBA\uFF1A${who2}\uFF09` : "\uFF08\u8BE5\u7248\u672C\u65E0\u4EBA\u6295\u7968\uFF09"}`);
214372
214607
  }
214373
214608
  const owner = model.artifacts.get(rev.artifactId);
214374
214609
  return {
@@ -214893,10 +215128,10 @@ async function startOasisServer(opts) {
214893
215128
  ...fp(p4)
214894
215129
  }))
214895
215130
  ] : [];
214896
- const { randomUUID: randomUUID51 } = await import("node:crypto");
215131
+ const { randomUUID: randomUUID53 } = await import("node:crypto");
214897
215132
  try {
214898
215133
  await store.enqueuePendingMessage({
214899
- id: randomUUID51(),
215134
+ id: randomUUID53(),
214900
215135
  chatSessionId: input.chatSessionId,
214901
215136
  text: input.text,
214902
215137
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -214929,11 +215164,11 @@ async function startOasisServer(opts) {
214929
215164
  ...f6?.mtime ? { srcMtime: f6.mtime } : {}
214930
215165
  };
214931
215166
  });
214932
- const { randomUUID: randomUUID51 } = await import("node:crypto");
215167
+ const { randomUUID: randomUUID53 } = await import("node:crypto");
214933
215168
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
214934
215169
  try {
214935
215170
  await store.enqueuePendingMessage({
214936
- id: randomUUID51(),
215171
+ id: randomUUID53(),
214937
215172
  chatSessionId: input.chatSessionId,
214938
215173
  text: "",
214939
215174
  createdAt: nowIso,
@@ -216427,7 +216662,7 @@ async function startOasisServer(opts) {
216427
216662
  const openRoom = async () => {
216428
216663
  let chatSessionId2;
216429
216664
  if (chatStore) {
216430
- const { randomUUID: randomUUID51 } = await import("node:crypto");
216665
+ const { randomUUID: randomUUID53 } = await import("node:crypto");
216431
216666
  const known = discussSessions.get(itemKey);
216432
216667
  const knownSession = known ? await chatStore.getSession(known) : null;
216433
216668
  if (knownSession && knownSession.workspace === ctx.workspace && knownSession.humanActorId === ctx.ownerId && (!body2.escalationId || knownSession.escalationId === body2.escalationId)) chatSessionId2 = known;
@@ -216436,7 +216671,7 @@ async function startOasisServer(opts) {
216436
216671
  chatSessionId2 = existing[0]?.id;
216437
216672
  }
216438
216673
  if (!chatSessionId2) {
216439
- chatSessionId2 = randomUUID51();
216674
+ chatSessionId2 = randomUUID53();
216440
216675
  const now = (/* @__PURE__ */ new Date()).toISOString();
216441
216676
  const title = `\u89E3\u51B3\uFF1A${ctx.seed.slice(ctx.seed.indexOf("\uFF1A") + 1, ctx.seed.indexOf("\uFF1A") + 25) || "\u5DE5\u5355\u5361\u70B9"}`;
216442
216677
  const reg0 = (await resolveEngine(currentCompanyId).catch(() => null))?.registry ?? opts.registry;
@@ -217657,7 +217892,7 @@ ${composed}`;
217657
217892
  if (rejectedLedger.failures === 0 && retriedRow) {
217658
217893
  turnPersisted = true;
217659
217894
  } else if (rejectedLedger.failures === 0) {
217660
- const { randomUUID: randomUUID51 } = await import("node:crypto");
217895
+ const { randomUUID: randomUUID53 } = await import("node:crypto");
217661
217896
  const now = (/* @__PURE__ */ new Date()).toISOString();
217662
217897
  const rejectedAttachments = effectiveAttachments.map((a5) => ({
217663
217898
  name: a5.name,
@@ -217665,7 +217900,7 @@ ${composed}`;
217665
217900
  ...a5.contentType !== void 0 ? { contentType: a5.contentType } : {}
217666
217901
  }));
217667
217902
  await chatStore.appendMessage({
217668
- id: randomUUID51(),
217903
+ id: randomUUID53(),
217669
217904
  sessionId: persistTarget.id,
217670
217905
  role: "user",
217671
217906
  content: persistedUserMessage,
@@ -217750,14 +217985,14 @@ ${composed}`;
217750
217985
  runtimeSessionId: session.nativeSessionId ?? session.id
217751
217986
  }).catch(() => void 0);
217752
217987
  }
217753
- const { randomUUID: randomUUID51 } = await import("node:crypto");
217988
+ const { randomUUID: randomUUID53 } = await import("node:crypto");
217754
217989
  const persistAttachments = effectiveAttachments.map((a5) => ({
217755
217990
  name: a5.name,
217756
217991
  ...a5.blobRef !== void 0 ? { blobRef: a5.blobRef } : {},
217757
217992
  ...a5.contentType !== void 0 ? { contentType: a5.contentType } : {}
217758
217993
  }));
217759
217994
  if (!retriedRow) await chatStore.appendMessage({
217760
- id: randomUUID51(),
217995
+ id: randomUUID53(),
217761
217996
  sessionId: persistTarget.id,
217762
217997
  role: "user",
217763
217998
  content: persistedUserMessage,
@@ -218409,8 +218644,8 @@ ${composed}`;
218409
218644
  res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: `\u56DE\u8C03\u5730\u5740\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4E2D\u6B62\uFF08\u907F\u514D\u5728 GitHub \u4E0A\u7559\u4E0B\u5B64\u513F App\uFF09\uFF1A${e5.message}` }));
218410
218645
  return;
218411
218646
  }
218412
- const { randomUUID: randomUUID51 } = await import("node:crypto");
218413
- const state2 = randomUUID51();
218647
+ const { randomUUID: randomUUID53 } = await import("node:crypto");
218648
+ const state2 = randomUUID53();
218414
218649
  const nameSlug = (actorName || actorId?.split(":").pop() || owner?.login || "bot").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "").slice(0, 24) || "bot";
218415
218650
  const nameSuffix = await chooseAppNameSuffix(
218416
218651
  { employeeSlug: nameSlug, namePrefix: "oasis" },
@@ -219202,10 +219437,10 @@ ${composed}`;
219202
219437
  await svc.putVariable({ key: "FEISHU_APP_ID", value: appId, scope: "global", connectorId: "feishu", encrypted: true });
219203
219438
  await svc.upsertConnector({ id: "feishu", name: "\u98DE\u4E66", mode: "oauth", status: "connected", account: appId });
219204
219439
  }
219205
- const who = await fetchFeishuUserIdentity(String(data["access_token"]));
219440
+ const who2 = await fetchFeishuUserIdentity(String(data["access_token"]));
219206
219441
  await withConnectorCredentialLock("feishu", actorId, () => persistFeishuUserAuthorization(svc, actorId, data, Date.now(), {
219207
- ...who.openId ? { openId: who.openId } : {},
219208
- ...who.name ? { userName: who.name } : {},
219442
+ ...who2.openId ? { openId: who2.openId } : {},
219443
+ ...who2.name ? { userName: who2.name } : {},
219209
219444
  ...isHumanActorId(actor) ? { authorizedBy: actor } : {}
219210
219445
  }));
219211
219446
  const nameScope = actorId ? { scope: "personal", actorId } : { scope: "global" };
@@ -219235,7 +219470,7 @@ ${composed}`;
219235
219470
  console.error(`[feishu-oauth] \u5F85\u5BA1\u6279\u8BB0\u5F55\u5199\u5165\u5931\u8D25: ${String(e5)}`);
219236
219471
  }
219237
219472
  }
219238
- if (!who.openId) console.error("[feishu-oauth] user_info \u672A\u53D6\u5230\u6388\u6743\u4EBA open_id\uFF1A\u6388\u6743\u5931\u6548\u65F6\u65E0\u6CD5\u79C1\u4FE1\u672C\u4EBA\u3001\u4E5F\u7B7E\u4E0D\u51FA\u4E00\u952E\u91CD\u65B0\u6388\u6743\u94FE\u63A5");
219473
+ if (!who2.openId) console.error("[feishu-oauth] user_info \u672A\u53D6\u5230\u6388\u6743\u4EBA open_id\uFF1A\u6388\u6743\u5931\u6548\u65F6\u65E0\u6CD5\u79C1\u4FE1\u672C\u4EBA\u3001\u4E5F\u7B7E\u4E0D\u51FA\u4E00\u952E\u91CD\u65B0\u6388\u6743\u94FE\u63A5");
219239
219474
  try {
219240
219475
  const secret = await svc.revealResolvedVariable("FEISHU_APP_SECRET", actorId);
219241
219476
  if (secret) {
@@ -230841,10 +231076,10 @@ async function scanZeroOutputBreaker(deps) {
230841
231076
  closingRemark
230842
231077
  });
230843
231078
  tripped.push(b6.artifactId);
230844
- const who = axis === "count" ? `${b6.actorId}\uFF08${b6.cls}\uFF09` : "\u8BE5\u8282\u70B9\u5168\u90E8\u6267\u884C\u4EBA\u5408\u8BA1";
231079
+ const who2 = axis === "count" ? `${b6.actorId}\uFF08${b6.cls}\uFF09` : "\u8BE5\u8282\u70B9\u5168\u90E8\u6267\u884C\u4EBA\u5408\u8BA1";
230845
231080
  const cidTag = deps.defaultCompanyId && b6.companyId !== deps.defaultCompanyId ? ` [${b6.companyId}]` : "";
230846
231081
  deps.log?.(
230847
- `[zero-output-breaker] ${b6.artifactId}${cidTag}\uFF1A\u6700\u8FD1 ${Math.round(deps.windowMs / 6e4)} \u5206\u949F\u5185 ${who} \u7D2F\u8BA1 ${b6.count} \u6B21\u96F6\u4EA7\u51FA\uFF08${b6.rounds.size} \u8F6E\uFF0C\u7EA6 $${(b6.costUsdMicros / 1e6).toFixed(1)}\uFF09\u2192 ${axis} \u8F74\u8DF3\u95F8`
231082
+ `[zero-output-breaker] ${b6.artifactId}${cidTag}\uFF1A\u6700\u8FD1 ${Math.round(deps.windowMs / 6e4)} \u5206\u949F\u5185 ${who2} \u7D2F\u8BA1 ${b6.count} \u6B21\u96F6\u4EA7\u51FA\uFF08${b6.rounds.size} \u8F6E\uFF0C\u7EA6 $${(b6.costUsdMicros / 1e6).toFixed(1)}\uFF09\u2192 ${axis} \u8F74\u8DF3\u95F8`
230848
231083
  );
230849
231084
  };
230850
231085
  const byKey = (a5, b6) => a5.artifactId.localeCompare(b6.artifactId) || (a5.actorId ?? "").localeCompare(b6.actorId ?? "");
@@ -230881,9 +231116,9 @@ ${t.closingRemark.trim()}` : "";
230881
231116
 
230882
231117
  ` + tail;
230883
231118
  }
230884
- const who = t.cls === "review" ? `\u8BC4\u5BA1\u5458 ${t.actorId}` : `\u6267\u884C\u4EBA ${t.actorId}`;
231119
+ const who2 = t.cls === "review" ? `\u8BC4\u5BA1\u5458 ${t.actorId}` : `\u6267\u884C\u4EBA ${t.actorId}`;
230885
231120
  const what = t.cls === "review" ? `\u5DF2\u505C\u6389\u8FD9\u540D\u8BC4\u5BA1\u5458\u5728\u672C\u8282\u70B9\u4E0A\u7684\u8BC4\u5BA1\uFF08**\u4EA4\u4ED8\u5185\u5BB9\u539F\u6837\u4FDD\u7559**\uFF0C\u6062\u590D\u540E\u53EF\u7EE7\u7EED\u6295\u7968\uFF09` : `\u5DF2\u81EA\u52A8\u6682\u505C\u8BE5\u4EA7\u7269\u7684\u6D3E\u53D1\u4EE5\u6B62\u635F`;
230886
- return `${who} \u5728\u6700\u8FD1 ${mins} \u5206\u949F\u5185\u4E3A\u8FD9\u4E2A\u4EA7\u7269\u8DD1\u4E86 ${t.workCount} \u8F6E\uFF0C**\u6BCF\u4E00\u8F6E\u90FD\u4EC0\u4E48\u90FD\u6CA1\u4EA4\u51FA\u6765**\uFF08${runs}\u8FD9\u4E9B\u7A7A\u8DD1\u7D2F\u8BA1\u82B1\u8D39\u7EA6 $${usd2}\uFF09\uFF0C${what}\u3002
231121
+ return `${who2} \u5728\u6700\u8FD1 ${mins} \u5206\u949F\u5185\u4E3A\u8FD9\u4E2A\u4EA7\u7269\u8DD1\u4E86 ${t.workCount} \u8F6E\uFF0C**\u6BCF\u4E00\u8F6E\u90FD\u4EC0\u4E48\u90FD\u6CA1\u4EA4\u51FA\u6765**\uFF08${runs}\u8FD9\u4E9B\u7A7A\u8DD1\u7D2F\u8BA1\u82B1\u8D39\u7EA6 $${usd2}\uFF09\uFF0C${what}\u3002
230887
231122
 
230888
231123
  ` + tail;
230889
231124
  }
@@ -242337,9 +242572,9 @@ function buildWorkorderActivity(input) {
242337
242572
  if (!worded.length) continue;
242338
242573
  const last = worded.at(-1);
242339
242574
  const name = nodeName(card2.nodeId);
242340
- const who = personOf(card2.executorId);
242575
+ const who2 = personOf(card2.executorId);
242341
242576
  const n3 = last.count ?? card2.foldedRounds ?? card2.traceWorkIds?.length ?? 1;
242342
- const sentence = last.kind === "retry_exhausted" ? ACTIVITY_COPY.retryExhausted(who, name, n3, lastFailureOf(card2, last) ?? last.lastReason) : ACTIVITY_COPY.outputStalled(who, name, n3, last.cost);
242577
+ const sentence = last.kind === "retry_exhausted" ? ACTIVITY_COPY.retryExhausted(who2, name, n3, lastFailureOf(card2, last) ?? last.lastReason) : ACTIVITY_COPY.outputStalled(who2, name, n3, last.cost);
242343
242578
  card2.status = worded.length > 1 ? ACTIVITY_COPY.stopLossAgain(sentence, worded.length) : sentence;
242344
242579
  }
242345
242580
  const reviewedWorkIds = new Set([...snap.reviews, ...activityReviews(snap, events)].map((r5) => r5.targetWorkId));
@@ -243451,7 +243686,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
243451
243686
  const gaps = unresolvedGapsOf(model, a5.id);
243452
243687
  const escalations = unresolvedEscalationsOf(model, a5.id);
243453
243688
  const representedEscalations = /* @__PURE__ */ new Set();
243454
- const who = isOwnerRecipient ? "\uFF08\u4F60\u662F\u5DE5\u5355\u5F52\u5C5E\u4EBA\uFF09" : "\uFF08\u4F60\u662F\u5361\u4F4F\u8282\u70B9 owner \u7684\u4E0A\u7EA7\uFF09";
243689
+ const who2 = isOwnerRecipient ? "\uFF08\u4F60\u662F\u5DE5\u5355\u5F52\u5C5E\u4EBA\uFF09" : "\uFF08\u4F60\u662F\u5361\u4F4F\u8282\u70B9 owner \u7684\u4E0A\u7EA7\uFF09";
243455
243690
  for (const gap of gaps) {
243456
243691
  const byGapId = escalations.filter((entry) => entry.gapId === gap.gapId);
243457
243692
  const samePartGaps = gaps.filter((candidate) => candidate.part === gap.part);
@@ -243510,7 +243745,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
243510
243745
  // ADR-0108 D10:**不再截到 100 字**。熔断升级卡走的正是这条「无 gap」分支,而 D10 刚
243511
243746
  // 往里放进了真正有用的东西(末次失败原文、哪台机器死了多久、去哪改绑)——一刀切到 100 字
243512
243747
  // 会把它们全砍掉,只剩「连败 N 次」这种人早就知道的部分。前端按卡片排版自己收,不在这里截。
243513
- summary: `\u300C${nodeLabel(a5)}\u300D\u9700\u8981\u4F60\u5904\u7406${who}\uFF1A${e5.reason}`
243748
+ summary: `\u300C${nodeLabel(a5)}\u300D\u9700\u8981\u4F60\u5904\u7406${who2}\uFF1A${e5.reason}`
243514
243749
  });
243515
243750
  }
243516
243751
  }
@@ -243972,7 +244207,7 @@ function sessionLabel(s3) {
243972
244207
  const t = (s3.title ?? "").trim();
243973
244208
  return t.length > 0 ? t : "\u672A\u547D\u540D\u4F1A\u8BDD";
243974
244209
  }
243975
- async function buildChatPreview(chatStore, sessionId, who) {
244210
+ async function buildChatPreview(chatStore, sessionId, who2) {
243976
244211
  let msgs;
243977
244212
  if (chatStore.listRecentTurns) {
243978
244213
  msgs = (await chatStore.listRecentTurns(sessionId, 1)).messages;
@@ -243983,7 +244218,7 @@ async function buildChatPreview(chatStore, sessionId, who) {
243983
244218
  const lastAsst = [...msgs].reverse().find((m4) => m4.role === "assistant" && m4.content.trim().length > 0);
243984
244219
  const lines = [];
243985
244220
  if (lastUser) lines.push({ label: "\u4F60", text: clip3(lastUser.content) });
243986
- if (lastAsst) lines.push({ label: who, text: clip3(lastAsst.content) });
244221
+ if (lastAsst) lines.push({ label: who2, text: clip3(lastAsst.content) });
243987
244222
  return lines.length ? { lines } : void 0;
243988
244223
  }
243989
244224
  async function buildChatInbox(chatStore, markers, me, resolveActor, excludeChildSessions) {
@@ -243995,10 +244230,10 @@ async function buildChatInbox(chatStore, markers, me, resolveActor, excludeChild
243995
244230
  let previewsFetched = 0;
243996
244231
  for (const s3 of unread) {
243997
244232
  if (excluded.has(s3.id)) continue;
243998
- const who = resolveActor?.(s3.aiActorId)?.name ?? "\u52A9\u7406";
243999
- const whoText = resolveActor?.(s3.aiActorId)?.name ? `${atActorName(who)} ` : who;
244233
+ const who2 = resolveActor?.(s3.aiActorId)?.name ?? "\u52A9\u7406";
244234
+ const whoText = resolveActor?.(s3.aiActorId)?.name ? `${atActorName(who2)} ` : who2;
244000
244235
  const abnormal = s3.lastTurnQuality === "abnormal";
244001
- const preview2 = previewsFetched < PREVIEW_FETCH_CAP ? await buildChatPreview(chatStore, s3.id, who) : void 0;
244236
+ const preview2 = previewsFetched < PREVIEW_FETCH_CAP ? await buildChatPreview(chatStore, s3.id, who2) : void 0;
244002
244237
  if (preview2) previewsFetched++;
244003
244238
  out.push({
244004
244239
  kind: abnormal ? "chat-interrupted" : "chat-replied",
@@ -251504,9 +251739,9 @@ var init_allocate = __esm({
251504
251739
  function describeRejections(rejections) {
251505
251740
  return rejections.map((r5) => `${r5.nodeName} \xB7 ${r5.runtimeKind}\uFF08${CAUSE_TEXT[r5.cause]}${r5.detail ? `\uFF1A${r5.detail}` : ""}\uFF09`).join("\uFF1B");
251506
251741
  }
251507
- function describeAllocationFailure(result, who) {
251508
- const subject = who?.actorName?.trim() ? `${atActorName(who.actorName.trim())} ` : "\u8FD9\u4F4D Agent";
251509
- const what = who?.what?.trim() ? `${who.what.trim()}\uFF1A` : "";
251742
+ function describeAllocationFailure(result, who2) {
251743
+ const subject = who2?.actorName?.trim() ? `${atActorName(who2.actorName.trim())} ` : "\u8FD9\u4F4D Agent";
251744
+ const what = who2?.what?.trim() ? `${who2.what.trim()}\uFF1A` : "";
251510
251745
  const detail = describeRejections(result.rejections);
251511
251746
  if (result.reason === "no-candidates") {
251512
251747
  return {
@@ -251528,9 +251763,9 @@ function describeAllocationFailure(result, who) {
251528
251763
  message: `${what}${subject}\u7684\u8FD0\u884C\u65F6\u76EE\u524D\u90FD\u4E0D\u53EF\u7528\uFF0C\u672C\u6B21\u6CA1\u6709\u6D3E\u51FA\uFF1A${detail}\u3002\u8BF7\u786E\u8BA4\u90A3\u4E9B\u673A\u5668\u5F00\u7740\u3001\u8282\u70B9\u7A0B\u5E8F\u5728\u8FD0\u884C\u3001\u8FD0\u884C\u65F6\u5DF2\u767B\u5F55\u4E14\u989D\u5EA6\u672A\u8017\u5C3D\uFF1B\u6216\u5728\u5458\u5DE5\u8BE6\u60C5\u9875\u52A0\u4E00\u6761\u522B\u7684\u5019\u9009\u8FD0\u884C\u65F6\u3002`
251529
251764
  };
251530
251765
  }
251531
- function requireAllocation(result, who) {
251766
+ function requireAllocation(result, who2) {
251532
251767
  if (result.ok) return result;
251533
- const failure2 = describeAllocationFailure(result, who);
251768
+ const failure2 = describeAllocationFailure(result, who2);
251534
251769
  throw new RuntimeAllocationError(failure2.code, failure2.message, result.rejections, failure2.status);
251535
251770
  }
251536
251771
  var RuntimeAllocationError, CAUSE_TEXT;
@@ -252371,8 +252606,8 @@ function resolvedByMe(row, evs, me, onNode) {
252371
252606
  function resolvedByOther(row, evs, me, onNode) {
252372
252607
  const gen = generationOfKey(row.sourceKey);
252373
252608
  for (const rec2 of evs) {
252374
- const who = doerOf(rec2);
252375
- if (who === me) continue;
252609
+ const who2 = doerOf(rec2);
252610
+ if (who2 === me) continue;
252376
252611
  switch (row.kind) {
252377
252612
  case "review-request":
252378
252613
  case "review-waiting": {
@@ -252382,14 +252617,14 @@ function resolvedByOther(row, evs, me, onNode) {
252382
252617
  const vv = payload(x2, "review.response");
252383
252618
  return !!vv && vv.targetWorkId === gen && vv.reviewerActorId !== me;
252384
252619
  });
252385
- return found(rec2, invalidated("handled-by-other", rec2.createdAt, decider ? doerOf(decider) : who));
252620
+ return found(rec2, invalidated("handled-by-other", rec2.createdAt, decider ? doerOf(decider) : who2));
252386
252621
  }
252387
252622
  break;
252388
252623
  }
252389
252624
  case "gap-escalation":
252390
252625
  case "pushback": {
252391
252626
  const r5 = payload(rec2, "issue.resolve");
252392
- if (r5 && issueIdsOf(row).has(r5.issueId)) return found(rec2, invalidated("handled-by-other", rec2.createdAt, who));
252627
+ if (r5 && issueIdsOf(row).has(r5.issueId)) return found(rec2, invalidated("handled-by-other", rec2.createdAt, who2));
252393
252628
  break;
252394
252629
  }
252395
252630
  case "needs-staffing": {
@@ -252402,7 +252637,7 @@ function resolvedByOther(row, evs, me, onNode) {
252402
252637
  case "stale":
252403
252638
  case "work-waiting": {
252404
252639
  const acc = payload(rec2, "work.accept");
252405
- if (acc && onNode(rec2)) return found(rec2, invalidated("handled-by-other", rec2.createdAt, who));
252640
+ if (acc && onNode(rec2)) return found(rec2, invalidated("handled-by-other", rec2.createdAt, who2));
252406
252641
  break;
252407
252642
  }
252408
252643
  default:
@@ -255848,13 +256083,13 @@ function stallFacts(body2) {
255848
256083
  const rawCost = /约\s*\$([\d.]+)/.exec(body2)?.[1];
255849
256084
  const cost = rawCost !== void 0 && Number.isFinite(Number(rawCost)) ? `$${Number(rawCost).toFixed(2)}` : void 0;
255850
256085
  const remark = body2.split("\u6700\u8FD1\u4E00\u6B21\u8FD0\u884C\u7684\u6536\u5C3E\u53D1\u8A00\uFF08\u5F80\u5F80\u76F4\u63A5\u5199\u7740\u5361\u5728\u54EA\uFF09\uFF1A\n")[1]?.trim();
255851
- const who = /^(执行人|评审员)\s+(actor:\S+)/.exec(body2.trim());
256086
+ const who2 = /^(执行人|评审员)\s+(actor:\S+)/.exec(body2.trim());
255852
256087
  return {
255853
256088
  ...rounds !== void 0 ? { count: { n: rounds, unit: "\u8F6E" } } : runs !== void 0 ? { count: { n: runs, unit: "\u6B21\u8FD0\u884C" } } : {},
255854
256089
  ...minutes !== void 0 ? { minutes } : {},
255855
256090
  ...cost ? { cost } : {},
255856
256091
  ...remark ? { remark } : {},
255857
- ...who ? { actorId: who[2], stalled: who[1] === "\u8BC4\u5BA1\u5458" ? "review" : "produce" } : {}
256092
+ ...who2 ? { actorId: who2[2], stalled: who2[1] === "\u8BC4\u5BA1\u5458" ? "review" : "produce" } : {}
255858
256093
  };
255859
256094
  }
255860
256095
  function firstSentence2(text7) {
@@ -255872,17 +256107,17 @@ function reviewerUnavailableFacts(body2) {
255872
256107
  }
255873
256108
  function missingNodeFacts(body2) {
255874
256109
  const m4 = /指向(已删除|未注册)的节点\s+(\S+?)。/.exec(body2);
255875
- const who = /为执行人\s+(actor:\S+)\s+选择/.exec(body2);
255876
- return { ...m4 ? { gone: m4[1], runtimeNode: m4[2] } : {}, ...who ? { executorId: who[1] } : {} };
256110
+ const who2 = /为执行人\s+(actor:\S+)\s+选择/.exec(body2);
256111
+ return { ...m4 ? { gone: m4[1], runtimeNode: m4[2] } : {}, ...who2 ? { executorId: who2[1] } : {} };
255877
256112
  }
255878
256113
  function renderEscalationOpeningBody(facts) {
255879
256114
  const body2 = facts.body.trim();
255880
- const who = facts.actorName ? plainActor(facts.actorName) : void 0;
256115
+ const who2 = facts.actorName ? plainActor(facts.actorName) : void 0;
255881
256116
  if (facts.kind === "reviewer_unavailable") {
255882
256117
  const { reviewerId, role } = reviewerUnavailableFacts(body2);
255883
256118
  if (!reviewerId) return body2;
255884
256119
  return [
255885
- `\u300C${facts.nodeLabel ?? "\u8FD9\u4E00\u6B65"}\u300D\u9501\u5B9A\u7684\u5BA1\u6838\u4EBA${who ? ` ${who}` : ""}\uFF08${role} \u89D2\u8272\uFF09\u73B0\u5728\u4E0D\u53EF\u7528\u2014\u2014\u7194\u65AD\u3001\u79BB\u5C97\uFF0C\u6216\u8005\u5DF2\u88AB\u79FB\u51FA\u8FD9\u4E2A\u89D2\u8272\u2014\u2014\u8FD9\u4E00\u6B65\u7684\u8BC4\u5BA1\u6D3E\u4E0D\u51FA\u53BB\u3002`,
256120
+ `\u300C${facts.nodeLabel ?? "\u8FD9\u4E00\u6B65"}\u300D\u9501\u5B9A\u7684\u5BA1\u6838\u4EBA${who2 ? ` ${who2}` : ""}\uFF08${role} \u89D2\u8272\uFF09\u73B0\u5728\u4E0D\u53EF\u7528\u2014\u2014\u7194\u65AD\u3001\u79BB\u5C97\uFF0C\u6216\u8005\u5DF2\u88AB\u79FB\u51FA\u8FD9\u4E2A\u89D2\u8272\u2014\u2014\u8FD9\u4E00\u6B65\u7684\u8BC4\u5BA1\u6D3E\u4E0D\u51FA\u53BB\u3002`,
255886
256121
  "\u9700\u8981\u4F60\u5B9A\u4E00\u4E0B\uFF1A\u6362\u4E00\u4E2A\u5BA1\u6838\u4EBA\uFF0C\u8FD8\u662F\u7B49\u539F\u5BA1\u6838\u4EBA\u6062\u590D\u3002"
255887
256122
  ].join("\n\n");
255888
256123
  }
@@ -255890,7 +256125,7 @@ function renderEscalationOpeningBody(facts) {
255890
256125
  const { gone, runtimeNode } = missingNodeFacts(body2);
255891
256126
  if (!runtimeNode) return body2;
255892
256127
  return [
255893
- `\u300C${facts.nodeLabel ?? "\u8FD9\u4E00\u6B65"}\u300D\u8FD8\u6CA1\u6709\u542F\u52A8\uFF1A${who ?? "\u6267\u884C\u4EBA"}\u7ED1\u5B9A\u7684\u8FD0\u884C\u8282\u70B9 ${runtimeNode} ${gone === "\u672A\u6CE8\u518C" ? "\u6CA1\u6709\u6CE8\u518C\u8FC7" : "\u5DF2\u7ECF\u88AB\u5220\u9664"}\uFF0C\u6D3E\u4E0D\u51FA\u53BB\u3002\u8FD9\u6B21\u68C0\u67E5\u6CA1\u6709\u7EC8\u6B62\u4EFB\u4F55\u4F1A\u8BDD\uFF0C\u4E5F\u6CA1\u6709\u6D88\u8017\u91CD\u8BD5\u6B21\u6570\u3002`,
256128
+ `\u300C${facts.nodeLabel ?? "\u8FD9\u4E00\u6B65"}\u300D\u8FD8\u6CA1\u6709\u542F\u52A8\uFF1A${who2 ?? "\u6267\u884C\u4EBA"}\u7ED1\u5B9A\u7684\u8FD0\u884C\u8282\u70B9 ${runtimeNode} ${gone === "\u672A\u6CE8\u518C" ? "\u6CA1\u6709\u6CE8\u518C\u8FC7" : "\u5DF2\u7ECF\u88AB\u5220\u9664"}\uFF0C\u6D3E\u4E0D\u51FA\u53BB\u3002\u8FD9\u6B21\u68C0\u67E5\u6CA1\u6709\u7EC8\u6B62\u4EFB\u4F55\u4F1A\u8BDD\uFF0C\u4E5F\u6CA1\u6709\u6D88\u8017\u91CD\u8BD5\u6B21\u6570\u3002`,
255894
256129
  "\u9700\u8981\u4F60\u6062\u590D\u90A3\u53F0\u8282\u70B9\uFF0C\u6216\u8005\u7ED9\u6267\u884C\u4EBA\u6539\u7ED1\u4E00\u53F0\u5728\u7EBF\u7684\u8282\u70B9\uFF1B\u4FEE\u597D\u4E4B\u540E\u544A\u8BC9\u6211\uFF0C\u6211\u6765\u628A\u8FD9\u4E00\u6B65\u653E\u51FA\u53BB\u3002"
255895
256130
  ].join("\n\n");
255896
256131
  }
@@ -255899,7 +256134,7 @@ function renderEscalationOpeningBody(facts) {
255899
256134
  const { count: count3, lastReason } = retryFacts(body2);
255900
256135
  if (!count3) return body2;
255901
256136
  return [
255902
- `${who ?? "\u8FD9\u4E00\u6B65\u7684\u6267\u884C\u4EBA"}${at(facts.nodeLabel)}\u8FDE\u7EED ${count3.n} \u8F6E\u90FD\u6CA1\u8DD1\u6210\uFF0C\u81EA\u52A8\u91CD\u8BD5\u5DF2\u7ECF\u7528\u5B8C\u2014\u2014\u8FD9\u4E00\u6B65\u4E0D\u4F1A\u518D\u81EA\u52A8\u91CD\u6765\u4E86\u3002`,
256137
+ `${who2 ?? "\u8FD9\u4E00\u6B65\u7684\u6267\u884C\u4EBA"}${at(facts.nodeLabel)}\u8FDE\u7EED ${count3.n} \u8F6E\u90FD\u6CA1\u8DD1\u6210\uFF0C\u81EA\u52A8\u91CD\u8BD5\u5DF2\u7ECF\u7528\u5B8C\u2014\u2014\u8FD9\u4E00\u6B65\u4E0D\u4F1A\u518D\u81EA\u52A8\u91CD\u6765\u4E86\u3002`,
255903
256138
  ...lastReason ? [`\u6700\u540E\u4E00\u6B21\u5931\u8D25\u8BB0\u4E0B\u7684\u539F\u56E0\uFF1A${lastReason}`] : [],
255904
256139
  "\u9700\u8981\u4F60\u5B9A\u4E00\u4E0B\u63A5\u4E0B\u6765\u600E\u4E48\u529E\uFF1A\u6309\u539F\u65B9\u6848\u518D\u8BD5\u4E00\u6B21\u3001\u6539\u4E86\u4EFB\u52A1\u8BF4\u660E\u518D\u8DD1\uFF0C\u8FD8\u662F\u6362\u4E2A\u4EBA\u505A\u3002"
255905
256140
  ].join("\n\n");
@@ -255914,7 +256149,7 @@ function renderEscalationOpeningBody(facts) {
255914
256149
  }
255915
256150
  const { count: count2, minutes, cost, remark, stalled } = stallFacts(body2);
255916
256151
  if (!count2) return body2;
255917
- const subject = stalled ? `${who ?? (stalled === "review" ? "\u8FD9\u4E00\u6B65\u7684\u8BC4\u5BA1\u5458" : "\u8FD9\u4E00\u6B65\u7684\u6267\u884C\u4EBA")}${at(facts.nodeLabel)}` : `\u300C${facts.nodeLabel ?? "\u8FD9\u4E00\u6B65"}\u300D`;
256152
+ const subject = stalled ? `${who2 ?? (stalled === "review" ? "\u8FD9\u4E00\u6B65\u7684\u8BC4\u5BA1\u5458" : "\u8FD9\u4E00\u6B65\u7684\u6267\u884C\u4EBA")}${at(facts.nodeLabel)}` : `\u300C${facts.nodeLabel ?? "\u8FD9\u4E00\u6B65"}\u300D`;
255918
256153
  const window3 = minutes !== void 0 ? `\u6700\u8FD1 ${minutes} \u5206\u949F\u91CC` : "\u6700\u8FD1\u4E00\u6BB5\u65F6\u95F4\u91CC";
255919
256154
  const spent = cost ? `\uFF08\u8FD9\u4E9B\u7A7A\u8DD1\u5408\u8BA1\u5DF2\u7ECF\u82B1\u6389\u7EA6 ${cost}\uFF09` : "";
255920
256155
  const each = count2.unit === "\u8F6E" ? "\u6BCF\u4E00\u8F6E" : "\u6BCF\u4E00\u6B21";
@@ -257681,20 +257916,20 @@ function shown(field, v2, nameOf2) {
257681
257916
  if (field === "assignee") return nameOf2(v2);
257682
257917
  return clip4(v2);
257683
257918
  }
257684
- function assignedTitle(who, todo) {
257685
- return `${who} \u6D3E\u7ED9\u4F60\uFF1A${todo.title}\uFF0C${formatTodoSpan(todo)}`;
257919
+ function assignedTitle(who2, todo) {
257920
+ return `${who2} \u6D3E\u7ED9\u4F60\uFF1A${todo.title}\uFF0C${formatTodoSpan(todo)}`;
257686
257921
  }
257687
257922
  function unseenTitle(assigneeName, todo) {
257688
257923
  return `${assigneeName} \u8FD8\u6CA1\u770B\u8FC7\u8FD9\u6761\uFF1A${todo.title}\uFF0C\u660E\u5929\u622A\u6B62`;
257689
257924
  }
257690
- function changedTitle(who, todo, changes, nameOf2) {
257925
+ function changedTitle(who2, todo, changes, nameOf2) {
257691
257926
  const parts = changes.map((c5) => `${FIELD_LABEL[c5.field] ?? c5.field} ${shown(c5.field, c5.oldValue, nameOf2)} \u2192 ${shown(c5.field, c5.newValue, nameOf2)}`);
257692
257927
  const reason = changes.find((c5) => c5.reason)?.reason;
257693
- return `${who} \u6539\u4E86\u300C${todo.title}\u300D\uFF1A${parts.join("\uFF1B")}${reason ? `\uFF1B\u539F\u56E0\uFF1A${clip4(reason)}` : ""}`;
257928
+ return `${who2} \u6539\u4E86\u300C${todo.title}\u300D\uFF1A${parts.join("\uFF1B")}${reason ? `\uFF1B\u539F\u56E0\uFF1A${clip4(reason)}` : ""}`;
257694
257929
  }
257695
- function statusTitle(who, todo, kind, reason) {
257930
+ function statusTitle(who2, todo, kind, reason, result) {
257696
257931
  const verb = kind === "todo-done" ? "\u5B8C\u6210\u4E86" : kind === "todo-reopened" ? "\u91CD\u65B0\u6253\u5F00\u4E86" : "\u53D6\u6D88\u4E86";
257697
- return `${who} ${verb}\u300C${todo.title}\u300D${reason ? `\uFF1B\u539F\u56E0\uFF1A${clip4(reason)}` : ""}`;
257932
+ return `${who2} ${verb}\u300C${todo.title}\u300D${result ? `\uFF1B\u7ED3\u679C\uFF1A${clip4(result)}` : ""}${reason ? `\uFF1B\u539F\u56E0\uFF1A${clip4(reason)}` : ""}`;
257698
257933
  }
257699
257934
  var VALUE_MAX, FIELD_LABEL, clip4, todoAssignedSourceKey, todoChangeSourceKey, todoUnseenSourceKey;
257700
257935
  var init_notices = __esm({
@@ -257710,7 +257945,8 @@ var init_notices = __esm({
257710
257945
  dueDate: "\u622A\u6B62\u65E5",
257711
257946
  dueTime: "\u622A\u6B62\u65F6\u523B",
257712
257947
  linkedWorkorderId: "\u5173\u8054\u5DE5\u5355",
257713
- assignee: "\u627F\u63A5\u4EBA"
257948
+ assignee: "\u627F\u63A5\u4EBA",
257949
+ result: "\u7ED3\u679C\u5728\u54EA"
257714
257950
  };
257715
257951
  clip4 = (v2) => v2.length > VALUE_MAX ? `${v2.slice(0, VALUE_MAX)}\u2026` : v2;
257716
257952
  todoAssignedSourceKey = (todoId) => `todo:${todoId}@assigned`;
@@ -257745,7 +257981,7 @@ function assertStartBeforeDue(t) {
257745
257981
  throw new ApiError(400, "TODO_START_AFTER_DUE", `\u5F00\u59CB\uFF08${fmt(t.startDate, t.startTime)}\uFF09\u4E0D\u80FD\u665A\u4E8E\u622A\u6B62\uFF08${fmt(t.dueDate, t.dueTime)}\uFF09`);
257746
257982
  }
257747
257983
  }
257748
- var import_node_crypto71, TITLE_MAX, NOTE_MAX, REASON_MAX, LIST_MAX, clean2, TodoService;
257984
+ var import_node_crypto71, TITLE_MAX, NOTE_MAX, REASON_MAX, RESULT_MAX, LIST_MAX, clean2, TodoService;
257749
257985
  var init_service10 = __esm({
257750
257986
  "../server/src/domains/todos/service.ts"() {
257751
257987
  "use strict";
@@ -257756,6 +257992,7 @@ var init_service10 = __esm({
257756
257992
  TITLE_MAX = 200;
257757
257993
  NOTE_MAX = 4e3;
257758
257994
  REASON_MAX = 500;
257995
+ RESULT_MAX = 500;
257759
257996
  LIST_MAX = 500;
257760
257997
  clean2 = (v2) => {
257761
257998
  const t = v2?.trim();
@@ -258023,6 +258260,11 @@ var init_service10 = __esm({
258023
258260
  set("dueTime", input.dueTime ?? void 0);
258024
258261
  }
258025
258262
  if (input.linkedWorkorderId !== void 0) set("linkedWorkorderId", clean2(input.linkedWorkorderId));
258263
+ if (input.result !== void 0) {
258264
+ const result = clean2(input.result);
258265
+ if (result && result.length > RESULT_MAX) throw new ApiError(400, "TODO_INVALID", `result \u4E0D\u80FD\u8D85\u8FC7 ${RESULT_MAX} \u5B57`);
258266
+ set("result", result);
258267
+ }
258026
258268
  if (input.assignee !== void 0) {
258027
258269
  if (!isTodoUnsent(before)) throw new ApiError(400, "TODO_ASSIGNEE_LOCKED", "\u5DF2\u7ECF\u53D1\u51FA\u7684\u5F85\u529E\u4E0D\u80FD\u6362\u627F\u63A5\u4EBA\uFF1A\u53D6\u6D88\u8FD9\u6761\uFF08\u5E26\u539F\u56E0\uFF09\uFF0C\u518D\u91CD\u65B0\u6D3E\u4E00\u6761\u3002");
258028
258270
  const assignee = await this.resolvePerson(input.assignee, caller);
@@ -258060,15 +258302,22 @@ var init_service10 = __esm({
258060
258302
  /**
258061
258303
  * 完成 / 取消 / 重新打开。草案(从没发出过的):不能完成;取消了也仍只有发起人看得到;重新打开回到草案、不会因此发出去。
258062
258304
  * 别人派给我的,取消必须带原因(ADR 0640 D9)。派给别人且已发出的,动完通知另一方。
258305
+ *
258306
+ * 标完成可以顺带记「结果在哪」(`result`,ADR 0640 第二批):与状态同一次写入,单独一条 `field=result` 的变更记录;
258307
+ * 不给就不动原来的值(重开再完成不会把上次记的抹掉)。别的动作带 `result` 400——要改结果走 edit。
258063
258308
  */
258064
- async setStatus(caller, id, requested, reason) {
258309
+ async setStatus(caller, id, requested, reason, resultIn) {
258065
258310
  const before = await this.getForChange(caller, id);
258066
258311
  const why = clean2(reason);
258067
258312
  if (why && why.length > REASON_MAX) throw new ApiError(400, "TODO_INVALID", `reason \u4E0D\u80FD\u8D85\u8FC7 ${REASON_MAX} \u5B57`);
258313
+ const result = clean2(resultIn);
258314
+ if (result && requested !== "done") throw new ApiError(400, "TODO_INVALID", "result \u53EA\u5728\u6807\u5B8C\u6210\u65F6\u5E26\uFF1B\u8981\u6539\u7ED3\u679C\u5728\u54EA\u7528 oasis todo edit --result");
258315
+ if (result && result.length > RESULT_MAX) throw new ApiError(400, "TODO_INVALID", `result \u4E0D\u80FD\u8D85\u8FC7 ${RESULT_MAX} \u5B57`);
258068
258316
  const unsent = isTodoUnsent(before);
258069
258317
  if (unsent && requested === "done") throw new ApiError(400, "TODO_NOT_SENT", "\u8FD9\u6761\u8FD8\u662F\u8349\u6848\uFF08\u6CA1\u53D1\u51FA\uFF09\uFF0C\u4E0D\u80FD\u6807\u5B8C\u6210\uFF1A\u5148\u5728\u8349\u6848\u5361\u4E0A\u70B9\u300C\u53D1\u51FA\u300D\uFF0C\u6216\u53D6\u6D88\u5B83\u3002");
258070
258318
  if (before.status === "draft" && requested === "open") throw new ApiError(400, "TODO_NOT_SENT", "\u8FD9\u6761\u662F\u8349\u6848\uFF1A\u8981\u751F\u6548\u8BF7\u53D1\u8D77\u4EBA\u5728\u8349\u6848\u5361\u4E0A\u70B9\u300C\u53D1\u51FA\u300D\u3002");
258071
258319
  const status = unsent && requested === "open" ? "draft" : requested;
258320
+ if (before.status === status && status === "done" && result && result !== before.result) return this.edit(caller, id, { result });
258072
258321
  if (before.status === status) return this.respond(before);
258073
258322
  if (status === "cancelled" && !why && isTodoAssignedToByOther(before, caller.principal)) {
258074
258323
  throw new ApiError(400, "TODO_REASON_REQUIRED", "\u8FD9\u6761\u662F\u522B\u4EBA\u6D3E\u7ED9\u4F60\u7684\uFF1A\u53D6\u6D88\u8981\u5199\u539F\u56E0\uFF08--reason\uFF09\uFF0C\u53D1\u8D77\u4EBA\u4F1A\u6536\u5230\u901A\u77E5\u3002");
@@ -258080,7 +258329,12 @@ var init_service10 = __esm({
258080
258329
  if (status === "done") next.doneAt = at2;
258081
258330
  if (status === "cancelled") next.cancelledAt = at2;
258082
258331
  const change = this.change(id, caller, at2, "status", before.status, status, why);
258083
- const out = await this.save(caller, before, next, [change]);
258332
+ const changes = [change];
258333
+ if (result && result !== before.result) {
258334
+ next.result = result;
258335
+ changes.push(this.change(id, caller, at2, "result", before.result, result));
258336
+ }
258337
+ const out = await this.save(caller, before, next, changes);
258084
258338
  const kind = status === "done" ? "todo-done" : status === "cancelled" ? "todo-cancelled" : "todo-reopened";
258085
258339
  await this.notice(
258086
258340
  out.todo,
@@ -258088,7 +258342,7 @@ var init_service10 = __esm({
258088
258342
  this.counterparts(out.todo, caller),
258089
258343
  kind,
258090
258344
  todoChangeSourceKey(id, change.id),
258091
- statusTitle(await this.nameOf(caller.principal), out.todo, kind, why),
258345
+ statusTitle(await this.nameOf(caller.principal), out.todo, kind, why, status === "done" ? result : void 0),
258092
258346
  at2
258093
258347
  );
258094
258348
  return out;
@@ -258239,7 +258493,7 @@ function todosDomain(options) {
258239
258493
  }));
258240
258494
  const status = (path50, to) => router.post(`/api/todos/:id/${path50}`, wrap(async (req, service, caller) => {
258241
258495
  const body2 = statusBody.parse(req.body ?? {});
258242
- return { status: 200, body: await service.setStatus(caller, req.params.id, to, body2.reason) };
258496
+ return { status: 200, body: await service.setStatus(caller, req.params.id, to, body2.reason, body2.result) };
258243
258497
  }));
258244
258498
  status("done", "done");
258245
258499
  status("cancel", "cancelled");
@@ -258271,9 +258525,10 @@ var init_routes11 = __esm({
258271
258525
  startTime: external_exports.string().nullable().optional(),
258272
258526
  linkedWorkorderId: external_exports.string().nullable().optional(),
258273
258527
  assignee: external_exports.string().optional(),
258528
+ result: external_exports.string().nullable().optional(),
258274
258529
  reason: external_exports.string().optional()
258275
258530
  }).strict();
258276
- statusBody = external_exports.object({ reason: external_exports.string().optional() }).strict();
258531
+ statusBody = external_exports.object({ reason: external_exports.string().optional(), result: external_exports.string().optional() }).strict();
258277
258532
  }
258278
258533
  });
258279
258534
 
@@ -275189,6 +275444,19 @@ var init_postgres_delegations = __esm({
275189
275444
  );
275190
275445
  return r5.rows.map(toRecord2);
275191
275446
  }
275447
+ /**
275448
+ * 防重叠比对的委派池(ADR 0640 第二批):进行中与已交回的,失败的不给;任务书摘要取发起那次的流水(`kind='created'`)。
275449
+ * 只给服务端内部的比对服务用——委派列表接口不放开。
275450
+ */
275451
+ async listForOverlap() {
275452
+ const r5 = await this.pool.query(
275453
+ `SELECT d.*, t.text_digest AS created_text FROM ${this.s}.chat_session_delegations d
275454
+ LEFT JOIN ${this.s}.chat_session_delegation_touches t ON t.delegation_id = d.id AND t.kind = 'created'
275455
+ WHERE d.state IN ('running', 'done')
275456
+ ORDER BY d.created_at DESC, d.id`
275457
+ );
275458
+ return r5.rows.map((row) => delegationOverlapRowOf(toRecord2(row), row.created_text));
275459
+ }
275192
275460
  async patch(id, patch) {
275193
275461
  const sets = [];
275194
275462
  const vals = [];
@@ -305968,11 +306236,11 @@ var require_dist_cjs9 = __commonJS({
305968
306236
  throw new TokenProviderError2(`Value not present for '${key2}' in SSO Token${forRefresh ? ". Cannot refresh" : ""}. ${REFRESH_MESSAGE}`, false);
305969
306237
  }
305970
306238
  };
305971
- var { writeFile: writeFile13 } = promises5;
306239
+ var { writeFile: writeFile14 } = promises5;
305972
306240
  var writeSSOTokenToFile = (id, ssoToken) => {
305973
306241
  const tokenFilepath = getSSOTokenFilepath2(id);
305974
306242
  const tokenString = JSON.stringify(ssoToken, null, 2);
305975
- return writeFile13(tokenFilepath, tokenString);
306243
+ return writeFile14(tokenFilepath, tokenString);
305976
306244
  };
305977
306245
  var lastRefreshAttemptTimes = /* @__PURE__ */ new Map();
305978
306246
  var fromSso = (init = {}) => async ({ callerClientConfig } = {}) => {
@@ -309075,7 +309343,7 @@ var require_dist_cjs11 = __commonJS({
309075
309343
  var { createHash: createHash56, createPrivateKey: createPrivateKey2, createPublicKey, sign: sign6 } = require("node:crypto");
309076
309344
  var { promises: promises5 } = require("node:fs");
309077
309345
  var { homedir: homedir14 } = require("node:os");
309078
- var { dirname: dirname41, join: join54 } = require("node:path");
309346
+ var { dirname: dirname42, join: join54 } = require("node:path");
309079
309347
  var LoginCredentialsFetcher = class _LoginCredentialsFetcher {
309080
309348
  profileData;
309081
309349
  init;
@@ -309231,7 +309499,7 @@ var require_dist_cjs11 = __commonJS({
309231
309499
  }
309232
309500
  async saveToken(token2) {
309233
309501
  const tokenFilePath = this.getTokenFilePath();
309234
- const directory = dirname41(tokenFilePath);
309502
+ const directory = dirname42(tokenFilePath);
309235
309503
  try {
309236
309504
  await promises5.mkdir(directory, { recursive: true });
309237
309505
  } catch (error3) {
@@ -323812,14 +324080,14 @@ init_src();
323812
324080
  var os16 = __toESM(require("node:os"));
323813
324081
  var path49 = __toESM(require("node:path"));
323814
324082
  var import_node_child_process23 = require("node:child_process");
323815
- var import_node_crypto110 = require("node:crypto");
324083
+ var import_node_crypto112 = require("node:crypto");
323816
324084
 
323817
324085
  // ../cli/src/cli.ts
323818
324086
  init_src();
323819
324087
  var fs48 = __toESM(require("node:fs"), 1);
323820
324088
  var os13 = __toESM(require("node:os"), 1);
323821
324089
  var path42 = __toESM(require("node:path"), 1);
323822
- var import_node_crypto108 = require("node:crypto");
324090
+ var import_node_crypto110 = require("node:crypto");
323823
324091
 
323824
324092
  // ../cli/src/serve.ts
323825
324093
  init_src11();
@@ -323833,7 +324101,7 @@ var fs40 = __toESM(require("node:fs"), 1);
323833
324101
  var os9 = __toESM(require("node:os"), 1);
323834
324102
  var path32 = __toESM(require("node:path"), 1);
323835
324103
  var import_node_child_process15 = require("node:child_process");
323836
- var import_node_crypto102 = require("node:crypto");
324104
+ var import_node_crypto104 = require("node:crypto");
323837
324105
  var import_node_url7 = require("node:url");
323838
324106
 
323839
324107
  // ../cli/src/artifact-discovery-source.ts
@@ -325963,6 +326231,289 @@ function createTodoRuntime(options) {
325963
326231
  };
325964
326232
  }
325965
326233
 
326234
+ // ../cli/src/overlap-wiring.ts
326235
+ init_src();
326236
+ init_workorders();
326237
+
326238
+ // ../server/src/domains/overlap/service.ts
326239
+ var import_node_crypto101 = require("node:crypto");
326240
+ init_src();
326241
+ var QUERY_MAX = 4e3;
326242
+ var WORKORDER_ACTIVE = /* @__PURE__ */ new Set(["awaiting_dispatch", "not_started", "executing", "pending", "blocked", "held"]);
326243
+ var OverlapService = class {
326244
+ constructor(deps) {
326245
+ this.deps = deps;
326246
+ }
326247
+ warn(error3) {
326248
+ this.deps.warn?.(error3);
326249
+ }
326250
+ async safe(what, run) {
326251
+ if (!run) return void 0;
326252
+ try {
326253
+ return await run();
326254
+ } catch (error3) {
326255
+ this.warn(new Error(`\u6BD4\u5BF9\u6C60\u300C${what}\u300D\u8BFB\u4E0D\u51FA\u6765\uFF0C\u8FD9\u4E00\u7C7B\u5148\u4E0D\u6BD4\uFF1A${String(error3)}`));
326256
+ return void 0;
326257
+ }
326258
+ }
326259
+ async check(companyId, caller, input) {
326260
+ if (!this.deps.enabled()) return { enabled: false, active: [], done: [] };
326261
+ const config2 = this.deps.config();
326262
+ const query = overlapTokens(input.text.slice(0, QUERY_MAX));
326263
+ const timeZone = await this.deps.timeZone?.(companyId).catch(() => void 0);
326264
+ const tz = timeZone ? { timeZone } : {};
326265
+ if (query.size === 0) return { enabled: true, active: [], done: [], ...tz };
326266
+ const sources = this.deps.sources(companyId);
326267
+ const subject = input.subjectId?.trim();
326268
+ const session = input.chatSessionId?.trim();
326269
+ const pool = [];
326270
+ const keep = (score) => score >= config2.minScore;
326271
+ for (const t of await this.safe("\u5F85\u529E", sources.todos) ?? []) {
326272
+ if (t.status !== "open" && t.status !== "done") continue;
326273
+ if (t.creatorActorId !== t.assigneeActorId && !t.sentAt) continue;
326274
+ if (subject && t.id === subject) continue;
326275
+ const score = overlapScore(query, t.title, [t.note, t.result].filter(Boolean).join("\n"));
326276
+ if (!keep(score)) continue;
326277
+ const c5 = {
326278
+ kind: "todo",
326279
+ phase: t.status === "open" ? "active" : "done",
326280
+ score,
326281
+ title: t.title,
326282
+ todoId: t.id,
326283
+ creatorActorId: t.creatorActorId,
326284
+ assigneeActorId: t.assigneeActorId,
326285
+ ...t.sourceChatSessionId ? { sourceChatSessionId: t.sourceChatSessionId } : {},
326286
+ ...t.status === "open" ? { dueDate: t.dueDate } : {},
326287
+ ...t.status === "done" && t.doneAt ? { doneAt: t.doneAt } : {},
326288
+ ...t.status === "done" && t.result ? { result: t.result } : {}
326289
+ };
326290
+ pool.push({ candidate: c5, updatedAt: t.updatedAt });
326291
+ }
326292
+ for (const w2 of await this.safe("\u5DE5\u5355", sources.workorders) ?? []) {
326293
+ if (subject && w2.id === subject) continue;
326294
+ const delivered = w2.progressExcludingBrief?.concluded ?? 0;
326295
+ const phase = WORKORDER_ACTIVE.has(w2.stage) ? "active" : w2.stage === "concluded" && delivered > 0 ? "done" : void 0;
326296
+ if (!phase) continue;
326297
+ const score = overlapScore(query, w2.title, [w2.goal, w2.description].filter(Boolean).join("\n"));
326298
+ if (!keep(score)) continue;
326299
+ const c5 = {
326300
+ kind: "workorder",
326301
+ phase,
326302
+ score,
326303
+ title: w2.title,
326304
+ workorderId: w2.id,
326305
+ ...w2.owner?.id ? { initiatorActorId: w2.owner.id } : {},
326306
+ ...w2.owner?.name ? { initiatorName: w2.owner.name } : {},
326307
+ // 引擎没有单独的「结束时间」:已结束的工单取最后一次变动时刻(结束后不会再动)。
326308
+ ...phase === "done" && w2.updatedAt ? { endedAt: w2.updatedAt } : {},
326309
+ ...phase === "done" ? { deliverableCount: delivered } : {}
326310
+ };
326311
+ pool.push({ candidate: c5, updatedAt: w2.updatedAt });
326312
+ }
326313
+ for (const d5 of await this.safe("\u59D4\u6D3E", sources.delegations) ?? []) {
326314
+ if (subject && d5.id === subject) continue;
326315
+ if (session && d5.parentSessionId === session) continue;
326316
+ if (d5.state === "done" && d5.artifactCount === 0) continue;
326317
+ const title = d5.taskDigest || d5.taskText.slice(0, 60);
326318
+ const score = overlapScore(query, title, [d5.taskText, d5.label].filter(Boolean).join("\n"));
326319
+ if (!keep(score)) continue;
326320
+ const c5 = {
326321
+ kind: "delegation",
326322
+ phase: d5.state === "running" ? "active" : "done",
326323
+ score,
326324
+ title,
326325
+ delegationId: d5.id,
326326
+ childSessionId: d5.childSessionId,
326327
+ parentSessionId: d5.parentSessionId,
326328
+ expertActorId: d5.expertActorId,
326329
+ artifactCount: d5.artifactCount,
326330
+ ...d5.state === "done" && d5.settledAt ? { settledAt: d5.settledAt } : {}
326331
+ };
326332
+ pool.push({ candidate: c5, updatedAt: d5.settledAt ?? d5.createdAt });
326333
+ }
326334
+ const rank = (a5, b6) => b6.candidate.score - a5.candidate.score || (a5.updatedAt < b6.updatedAt ? 1 : a5.updatedAt > b6.updatedAt ? -1 : 0);
326335
+ const active = pool.filter((s3) => s3.candidate.phase === "active").sort(rank).slice(0, config2.maxActive).map((s3) => s3.candidate);
326336
+ const done = pool.filter((s3) => s3.candidate.phase === "done").sort(rank).slice(0, config2.maxDone).map((s3) => s3.candidate);
326337
+ const picked = [...active, ...done];
326338
+ if (picked.length > 0) {
326339
+ await this.fillPeople(sources, picked);
326340
+ await this.record(companyId, caller, input, picked, config2.minScore);
326341
+ }
326342
+ return { enabled: true, active, done, ...tz };
326343
+ }
326344
+ /** 只给挑出来的那几条补人名与派活人(池子可能上百条,不为它们逐条查)。 */
326345
+ async fillPeople(sources, picked) {
326346
+ const delegations = picked.filter((c5) => c5.kind === "delegation");
326347
+ const delegators = delegations.length ? await this.safe("\u6D3E\u6D3B\u4EBA", sources.delegators ? () => sources.delegators(delegations.map((d5) => d5.parentSessionId)) : void 0) ?? {} : {};
326348
+ for (const d5 of delegations) {
326349
+ const who2 = delegators[d5.parentSessionId];
326350
+ if (who2) d5.delegatorActorId = who2;
326351
+ }
326352
+ const ids2 = /* @__PURE__ */ new Set();
326353
+ for (const c5 of picked) {
326354
+ if (c5.kind === "todo") {
326355
+ ids2.add(c5.creatorActorId);
326356
+ ids2.add(c5.assigneeActorId);
326357
+ } else if (c5.kind === "workorder") {
326358
+ if (c5.initiatorActorId && !c5.initiatorName) ids2.add(c5.initiatorActorId);
326359
+ } else {
326360
+ ids2.add(c5.expertActorId);
326361
+ if (c5.delegatorActorId) ids2.add(c5.delegatorActorId);
326362
+ }
326363
+ }
326364
+ const names = await this.safe("\u663E\u793A\u540D", sources.names ? () => sources.names([...ids2]) : void 0) ?? {};
326365
+ for (const c5 of picked) {
326366
+ if (c5.kind === "todo") {
326367
+ if (names[c5.creatorActorId]) c5.creatorName = names[c5.creatorActorId];
326368
+ if (names[c5.assigneeActorId]) c5.assigneeName = names[c5.assigneeActorId];
326369
+ } else if (c5.kind === "workorder") {
326370
+ if (!c5.initiatorName && c5.initiatorActorId && names[c5.initiatorActorId]) c5.initiatorName = names[c5.initiatorActorId];
326371
+ } else {
326372
+ if (names[c5.expertActorId]) c5.expertName = names[c5.expertActorId];
326373
+ if (c5.delegatorActorId && names[c5.delegatorActorId]) c5.delegatorName = names[c5.delegatorActorId];
326374
+ }
326375
+ }
326376
+ }
326377
+ async record(companyId, caller, input, picked, minScore) {
326378
+ if (!this.deps.events) return;
326379
+ const event = {
326380
+ id: `ovl_${(0, import_node_crypto101.randomUUID)()}`,
326381
+ at: new Date(this.deps.now?.() ?? Date.now()).toISOString(),
326382
+ principalActorId: caller.principal,
326383
+ actorId: caller.actor,
326384
+ action: input.action,
326385
+ ...input.subjectId?.trim() ? { subjectId: input.subjectId.trim() } : {},
326386
+ ...input.chatSessionId?.trim() ? { chatSessionId: input.chatSessionId.trim() } : {},
326387
+ candidates: picked.map((c5) => ({ kind: c5.kind, phase: c5.phase, id: overlapCandidateId(c5), score: c5.score })),
326388
+ minScore
326389
+ };
326390
+ try {
326391
+ await (await this.deps.events(companyId)).append(event);
326392
+ } catch (error3) {
326393
+ this.warn(new Error(`\u6BD4\u5BF9\u4E8B\u4EF6\u6CA1\u8BB0\u4E0A\uFF08\u5019\u9009\u7167\u5E38\u8FD4\u56DE\uFF09\uFF1A${String(error3)}`));
326394
+ }
326395
+ }
326396
+ async recentEvents(companyId, limit) {
326397
+ if (!this.deps.events) return [];
326398
+ return (await this.deps.events(companyId)).listRecent(limit);
326399
+ }
326400
+ };
326401
+
326402
+ // ../server/src/domains/overlap/routes.ts
326403
+ init_zod();
326404
+ init_src();
326405
+ init_router();
326406
+ var checkBody = external_exports.object({
326407
+ action: external_exports.enum([...OVERLAP_ACTIONS]),
326408
+ text: external_exports.string().max(2e4),
326409
+ subjectId: external_exports.string().max(200).optional(),
326410
+ chatSessionId: external_exports.string().max(200).optional()
326411
+ }).strict();
326412
+ function overlapDomain(options) {
326413
+ const wrap = (fn) => async (req) => {
326414
+ try {
326415
+ const companyId = req.auth.companyId ?? options.defaultCompanyId();
326416
+ return await fn(req, companyId, await options.resolveCaller(req.auth.actor, req.auth.companyId));
326417
+ } catch (e5) {
326418
+ if (e5 instanceof ZodError) throw new ApiError(400, "OVERLAP_INVALID", e5.issues.map((i5) => `${i5.path.join(".")}: ${i5.message}`).join("; "));
326419
+ throw e5;
326420
+ }
326421
+ };
326422
+ return (router) => {
326423
+ router.post("/api/overlap/candidates", wrap(async (req, companyId, caller) => {
326424
+ const body2 = checkBody.parse(req.body ?? {});
326425
+ const chatSessionId = req.auth.dispatch?.chatSessionId ?? body2.chatSessionId;
326426
+ return {
326427
+ status: 200,
326428
+ body: await options.service.check(companyId, caller, {
326429
+ action: body2.action,
326430
+ text: body2.text,
326431
+ ...body2.subjectId ? { subjectId: body2.subjectId } : {},
326432
+ ...chatSessionId ? { chatSessionId } : {}
326433
+ })
326434
+ };
326435
+ }));
326436
+ router.get("/api/overlap/events", wrap(async (req, companyId) => {
326437
+ const raw = Number(req.query.get("limit") ?? 50);
326438
+ const limit = Number.isInteger(raw) && raw > 0 ? Math.min(raw, 500) : 50;
326439
+ return { status: 200, body: { items: await options.service.recentEvents(companyId, limit) } };
326440
+ }));
326441
+ };
326442
+ }
326443
+
326444
+ // ../server/src/domains/overlap/flag.ts
326445
+ function overlapCheckEnabledFromEnv(env2 = process.env) {
326446
+ const raw = (env2["OASIS_OVERLAP_CHECK"] ?? "").trim().toLowerCase();
326447
+ return !(raw === "off" || raw === "0" || raw === "false");
326448
+ }
326449
+ var OVERLAP_DEFAULTS = { maxActive: 5, maxDone: 3, minScore: 0.3 };
326450
+ function intIn(raw, fallback2, max) {
326451
+ if (raw === void 0 || raw.trim() === "") return fallback2;
326452
+ const n3 = Number(raw);
326453
+ return Number.isInteger(n3) && n3 >= 0 && n3 <= max ? n3 : fallback2;
326454
+ }
326455
+ function scoreIn(raw, fallback2) {
326456
+ if (raw === void 0 || raw.trim() === "") return fallback2;
326457
+ const n3 = Number(raw);
326458
+ return Number.isFinite(n3) && n3 > 0 && n3 <= 1 ? n3 : fallback2;
326459
+ }
326460
+ function overlapConfigFromEnv(env2 = process.env) {
326461
+ return {
326462
+ maxActive: intIn(env2["OASIS_OVERLAP_MAX_ACTIVE"], OVERLAP_DEFAULTS.maxActive, 50),
326463
+ maxDone: intIn(env2["OASIS_OVERLAP_MAX_DONE"], OVERLAP_DEFAULTS.maxDone, 50),
326464
+ minScore: scoreIn(env2["OASIS_OVERLAP_MIN_SCORE"], OVERLAP_DEFAULTS.minScore)
326465
+ };
326466
+ }
326467
+
326468
+ // ../cli/src/overlap-wiring.ts
326469
+ var TODO_POOL_MAX = 5e3;
326470
+ function createOverlapRuntime(options) {
326471
+ const sources = (companyId) => ({
326472
+ todos: async () => (await options.todos(companyId)).search({
326473
+ statuses: ["open", "done"],
326474
+ // viewer 不是任何人:从没发出过的草案一条都不进池子(草案只有发起人看得到,也不该被比出来)。
326475
+ viewer: "actor:system:overlap",
326476
+ limit: TODO_POOL_MAX
326477
+ }),
326478
+ workorders: async () => buildWorkorderSummaries(await options.workorderModel(companyId)),
326479
+ delegations: async () => await (await options.delegations(companyId)).listForOverlap?.() ?? [],
326480
+ names: async (ids2) => {
326481
+ const out = {};
326482
+ const people = await options.people(companyId).catch(() => []);
326483
+ for (const p4 of people) if (ids2.includes(p4.actorId)) out[p4.actorId] = p4.name;
326484
+ for (const id of ids2) {
326485
+ if (out[id] || isHumanActorId(id)) continue;
326486
+ const name = await options.actorName(companyId, id).catch(() => void 0);
326487
+ if (name) out[id] = name;
326488
+ }
326489
+ return out;
326490
+ },
326491
+ delegators: async (sessionIds) => {
326492
+ const out = {};
326493
+ for (const id of new Set(sessionIds)) {
326494
+ const human = await options.sessionHuman(companyId, id).catch(() => void 0);
326495
+ if (human) out[id] = human;
326496
+ }
326497
+ return out;
326498
+ }
326499
+ });
326500
+ const service = new OverlapService({
326501
+ sources,
326502
+ events: options.events,
326503
+ config: () => overlapConfigFromEnv(),
326504
+ enabled: options.enabled ?? (() => overlapCheckEnabledFromEnv()),
326505
+ timeZone: options.timeZone,
326506
+ warn: options.warn
326507
+ });
326508
+ const resolveCaller = async (actorId, companyId) => {
326509
+ if (isHumanActorId(actorId)) return { principal: actorId, actor: actorId };
326510
+ const human = await options.boundHuman(actorId, companyId ?? options.defaultCompanyId()).catch(() => null);
326511
+ return { principal: human ?? actorId, actor: actorId };
326512
+ };
326513
+ const register = overlapDomain({ service, resolveCaller, defaultCompanyId: options.defaultCompanyId });
326514
+ return { service, register, resolveCaller };
326515
+ }
326516
+
325966
326517
  // ../cli/src/connector-renewal-wiring.ts
325967
326518
  init_src();
325968
326519
  init_src3();
@@ -326004,7 +326555,7 @@ function createConnectorRenewalRuntime(options) {
326004
326555
  const deliverInvalidNotice = async (companyId, store, actorId, marker) => {
326005
326556
  const prev = marker.notice ?? { inApp: false, dm: "pending", attempts: 0 };
326006
326557
  const state2 = { ...prev, attempts: prev.attempts + 1 };
326007
- const who = `actor=${actorId ?? "-"} \u7B2C ${state2.attempts}/${MAX_NOTICE_ATTEMPTS} \u6B21`;
326558
+ const who2 = `actor=${actorId ?? "-"} \u7B2C ${state2.attempts}/${MAX_NOTICE_ATTEMPTS} \u6B21`;
326008
326559
  const name = await agentName(companyId, actorId);
326009
326560
  const { recipients, authorizer } = await recipientsFor(companyId, store, actorId);
326010
326561
  const unverified = !authorizer && !await store.revealVariable(FEISHU_USER_OPEN_ID_VAR, actorId).catch(() => "?");
@@ -326029,7 +326580,7 @@ function createConnectorRenewalRuntime(options) {
326029
326580
  options.onNotifications?.(companyId, rows);
326030
326581
  state2.inApp = true;
326031
326582
  } catch (err) {
326032
- options.warn(new Error(`\u98DE\u4E66\u6388\u6743\u5931\u6548\u7AD9\u5185\u901A\u77E5\u672A\u5199\u5165\uFF08${who}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326583
+ options.warn(new Error(`\u98DE\u4E66\u6388\u6743\u5931\u6548\u7AD9\u5185\u901A\u77E5\u672A\u5199\u5165\uFF08${who2}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326033
326584
  }
326034
326585
  }
326035
326586
  if (state2.dm === "pending") {
@@ -326054,7 +326605,7 @@ function createConnectorRenewalRuntime(options) {
326054
326605
  state2.dm = "sent";
326055
326606
  }
326056
326607
  } catch (err) {
326057
- options.warn(new Error(`\u98DE\u4E66\u6388\u6743\u5931\u6548\u79C1\u4FE1\u53D1\u9001\u5931\u8D25\uFF08${who}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326608
+ options.warn(new Error(`\u98DE\u4E66\u6388\u6743\u5931\u6548\u79C1\u4FE1\u53D1\u9001\u5931\u8D25\uFF08${who2}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326058
326609
  }
326059
326610
  }
326060
326611
  if ((!state2.inApp || state2.dm === "pending") && state2.attempts >= MAX_NOTICE_ATTEMPTS) {
@@ -326107,7 +326658,7 @@ function createConnectorRenewalRuntime(options) {
326107
326658
  const deliverApprovalNotice = async (companyId, store, actorId, pending, app) => {
326108
326659
  const prev = pending.notice ?? { inApp: false, dm: "pending", attempts: 0 };
326109
326660
  const state2 = { ...prev, attempts: prev.attempts + 1 };
326110
- const who = `actor=${actorId ?? "-"} \u7B2C ${state2.attempts}/${MAX_NOTICE_ATTEMPTS} \u6B21`;
326661
+ const who2 = `actor=${actorId ?? "-"} \u7B2C ${state2.attempts}/${MAX_NOTICE_ATTEMPTS} \u6B21`;
326111
326662
  const name = await agentName(companyId, actorId);
326112
326663
  const modules = feishuPendingApprovalModules(pending);
326113
326664
  if (!state2.inApp) {
@@ -326132,7 +326683,7 @@ function createConnectorRenewalRuntime(options) {
326132
326683
  options.onNotifications?.(companyId, rows);
326133
326684
  state2.inApp = true;
326134
326685
  } catch (err) {
326135
- options.warn(new Error(`\u98DE\u4E66\u6743\u9650\u6279\u51C6\u7AD9\u5185\u901A\u77E5\u672A\u5199\u5165\uFF08${who}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326686
+ options.warn(new Error(`\u98DE\u4E66\u6743\u9650\u6279\u51C6\u7AD9\u5185\u901A\u77E5\u672A\u5199\u5165\uFF08${who2}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326136
326687
  }
326137
326688
  }
326138
326689
  if (state2.dm === "pending") {
@@ -326154,7 +326705,7 @@ function createConnectorRenewalRuntime(options) {
326154
326705
  state2.dm = "sent";
326155
326706
  }
326156
326707
  } catch (err) {
326157
- options.warn(new Error(`\u98DE\u4E66\u6743\u9650\u6279\u51C6\u79C1\u4FE1\u53D1\u9001\u5931\u8D25\uFF08${who}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326708
+ options.warn(new Error(`\u98DE\u4E66\u6743\u9650\u6279\u51C6\u79C1\u4FE1\u53D1\u9001\u5931\u8D25\uFF08${who2}\uFF0C\u4E0B\u4E00\u62CD\u91CD\u8BD5\uFF09: ${String(err)}`));
326158
326709
  }
326159
326710
  }
326160
326711
  if ((!state2.inApp || state2.dm === "pending") && state2.attempts >= MAX_NOTICE_ATTEMPTS) {
@@ -326218,11 +326769,11 @@ function createConnectorRenewalRuntime(options) {
326218
326769
  if (await store.revealVariable(FEISHU_USER_OPEN_ID_VAR, e5.actorId)) return;
326219
326770
  const accessToken = e5.outcome.credentials?.["user_access_token"];
326220
326771
  if (!accessToken) return;
326221
- const who = await fetchFeishuUserIdentity(accessToken);
326222
- if (!who.openId) return;
326772
+ const who2 = await fetchFeishuUserIdentity(accessToken);
326773
+ if (!who2.openId) return;
326223
326774
  await store.putVariable({
326224
326775
  key: FEISHU_USER_OPEN_ID_VAR,
326225
- value: who.openId,
326776
+ value: who2.openId,
326226
326777
  ...e5.actorId ? { scope: "personal", actorId: e5.actorId } : { scope: "global" },
326227
326778
  connectorId: "feishu",
326228
326779
  encrypted: false
@@ -326272,14 +326823,14 @@ function createConnectorRenewalRuntime(options) {
326272
326823
  const name = await agentName(claims.companyId, claims.actorId);
326273
326824
  await notifyFeishuUser(store, claims.actorId, claims.purpose === "supplement" ? `\u300C${name}\u300D\u7684\u98DE\u4E66\u6743\u9650\u5DF2\u8865\u4E0A\uFF0C\u7BA1\u7406\u5458\u6279\u51C6\u7684\u529F\u80FD\u73B0\u5728\u53EF\u4EE5\u4F7F\u7528\u4E86\u3002` : `\u300C${name}\u300D\u7684\u98DE\u4E66\u7528\u6237\u6388\u6743\u5DF2\u6062\u590D\u3002`).catch(() => void 0);
326274
326825
  },
326275
- onRejected: async (claims, who) => {
326826
+ onRejected: async (claims, who2) => {
326276
326827
  const store = await options.actors(claims.companyId);
326277
326828
  if (!store) return;
326278
326829
  const name = await agentName(claims.companyId, claims.actorId);
326279
326830
  await notifyFeishuUser(
326280
326831
  store,
326281
326832
  claims.actorId,
326282
- `\u6709\u4EBA\u7528\u53E6\u4E00\u4E2A\u98DE\u4E66\u8D26\u53F7${who.userName ? `\uFF08${who.userName}\uFF09` : ""}\u6253\u5F00\u4E86\u300C${name}\u300D\u7684\u91CD\u65B0\u6388\u6743\u94FE\u63A5\uFF0C\u5DF2\u88AB\u62D2\u7EDD\uFF0C\u6388\u6743\u672A\u6539\u53D8\u3002`,
326833
+ `\u6709\u4EBA\u7528\u53E6\u4E00\u4E2A\u98DE\u4E66\u8D26\u53F7${who2.userName ? `\uFF08${who2.userName}\uFF09` : ""}\u6253\u5F00\u4E86\u300C${name}\u300D\u7684\u91CD\u65B0\u6388\u6743\u94FE\u63A5\uFF0C\u5DF2\u88AB\u62D2\u7EDD\uFF0C\u6388\u6743\u672A\u6539\u53D8\u3002`,
326283
326834
  claims.subject
326284
326835
  ).catch(() => void 0);
326285
326836
  }
@@ -326332,6 +326883,7 @@ var PostgresTodoStore = class _PostgresTodoStore {
326332
326883
  await pool.query(`ALTER TABLE ${store.s}.todos ADD COLUMN IF NOT EXISTS sent_at timestamptz`);
326333
326884
  await pool.query(`ALTER TABLE ${store.s}.todos ADD COLUMN IF NOT EXISTS first_viewed_at timestamptz`);
326334
326885
  await pool.query(`ALTER TABLE ${store.s}.todos ADD COLUMN IF NOT EXISTS source_run_id text`);
326886
+ await pool.query(`ALTER TABLE ${store.s}.todos ADD COLUMN IF NOT EXISTS result text`);
326335
326887
  const check2 = await pool.query(`SELECT pg_get_constraintdef(c.oid) AS def FROM pg_constraint c
326336
326888
  JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace
326337
326889
  WHERE n.nspname = $1 AND t.relname = 'todos' AND c.conname = 'todos_status_check'`, [schema]);
@@ -326386,8 +326938,8 @@ var PostgresTodoStore = class _PostgresTodoStore {
326386
326938
  return this.tx(async (client) => {
326387
326939
  const r5 = await client.query(`INSERT INTO ${this.s}.todos (id,title,note,creator_actor_id,assignee_actor_id,recorded_by_actor_id,
326388
326940
  due_date,due_time,status,done_at,cancelled_at,source_chat_session_id,linked_workorder_id,created_at,updated_at,start_date,start_time,
326389
- sent_at,first_viewed_at,source_run_id)
326390
- VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) RETURNING *`, rowValues(todo));
326941
+ sent_at,first_viewed_at,source_run_id,result)
326942
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21) RETURNING *`, rowValues(todo));
326391
326943
  await this.insertChanges(client, changes);
326392
326944
  return fromRow3(r5.rows[0]);
326393
326945
  });
@@ -326401,8 +326953,8 @@ var PostgresTodoStore = class _PostgresTodoStore {
326401
326953
  const r5 = await client.query(`UPDATE ${this.s}.todos SET title=$2,note=$3,creator_actor_id=$4,assignee_actor_id=$5,
326402
326954
  recorded_by_actor_id=$6,due_date=$7,due_time=$8,status=$9,done_at=$10,cancelled_at=$11,source_chat_session_id=$12,
326403
326955
  linked_workorder_id=$13,created_at=$14,updated_at=$15,start_date=$16,start_time=$17,
326404
- sent_at=$18,first_viewed_at=COALESCE(first_viewed_at,$19),source_run_id=$20
326405
- WHERE id=$1 AND updated_at=$21::timestamptz RETURNING *`, [...rowValues(next), expectedUpdatedAt]);
326956
+ sent_at=$18,first_viewed_at=COALESCE(first_viewed_at,$19),source_run_id=$20,result=$21
326957
+ WHERE id=$1 AND updated_at=$22::timestamptz RETURNING *`, [...rowValues(next), expectedUpdatedAt]);
326406
326958
  if (!r5.rows[0]) return null;
326407
326959
  await this.insertChanges(client, changes);
326408
326960
  return fromRow3(r5.rows[0]);
@@ -326480,7 +327032,8 @@ function rowValues(t) {
326480
327032
  t.startTime ?? null,
326481
327033
  t.sentAt ?? null,
326482
327034
  t.firstViewedAt ?? null,
326483
- t.sourceRunId ?? null
327035
+ t.sourceRunId ?? null,
327036
+ t.result ?? null
326484
327037
  ];
326485
327038
  }
326486
327039
  function fromRow3(row) {
@@ -326506,12 +327059,103 @@ function fromRow3(row) {
326506
327059
  ["linkedWorkorderId", row["linked_workorder_id"]],
326507
327060
  ["sentAt", iso8(row["sent_at"])],
326508
327061
  ["firstViewedAt", iso8(row["first_viewed_at"])],
326509
- ["sourceRunId", row["source_run_id"]]
327062
+ ["sourceRunId", row["source_run_id"]],
327063
+ ["result", row["result"]]
326510
327064
  ];
326511
327065
  for (const [k6, v2] of opt) if (v2 !== void 0 && v2 !== null) t[k6] = v2;
326512
327066
  return t;
326513
327067
  }
326514
327068
 
327069
+ // ../storage/src/postgres-overlap-events.ts
327070
+ init_pg_ident();
327071
+ init_schema_ddl_lock();
327072
+ var PostgresOverlapEventStore = class _PostgresOverlapEventStore {
327073
+ constructor(pool, schema) {
327074
+ this.pool = pool;
327075
+ this.s = quoteIdent2(schema);
327076
+ }
327077
+ s;
327078
+ static async open(pool, schema) {
327079
+ const store = new _PostgresOverlapEventStore(pool, schema);
327080
+ await withSchemaDdlLock(pool, schema, async () => {
327081
+ await pool.query(`CREATE SCHEMA IF NOT EXISTS ${store.s}`);
327082
+ await pool.query(`CREATE TABLE IF NOT EXISTS ${store.s}.overlap_events (
327083
+ id text PRIMARY KEY,
327084
+ at timestamptz NOT NULL,
327085
+ principal_actor_id text NOT NULL,
327086
+ actor_id text NOT NULL,
327087
+ action text NOT NULL,
327088
+ subject_id text,
327089
+ chat_session_id text,
327090
+ candidates jsonb NOT NULL,
327091
+ min_score double precision NOT NULL
327092
+ )`);
327093
+ await pool.query(`CREATE INDEX IF NOT EXISTS overlap_events_at_idx ON ${store.s}.overlap_events (at DESC)`);
327094
+ });
327095
+ return store;
327096
+ }
327097
+ async append(e5) {
327098
+ await this.pool.query(
327099
+ `INSERT INTO ${this.s}.overlap_events (id,at,principal_actor_id,actor_id,action,subject_id,chat_session_id,candidates,min_score)
327100
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9) ON CONFLICT (id) DO NOTHING`,
327101
+ [e5.id, e5.at, e5.principalActorId, e5.actorId, e5.action, e5.subjectId ?? null, e5.chatSessionId ?? null, JSON.stringify(e5.candidates), e5.minScore]
327102
+ );
327103
+ }
327104
+ async listRecent(limit) {
327105
+ const r5 = await this.pool.query(`SELECT * FROM ${this.s}.overlap_events ORDER BY at DESC, id LIMIT $1`, [limit]);
327106
+ return r5.rows.map((row) => ({
327107
+ id: row.id,
327108
+ at: (row.at instanceof Date ? row.at : new Date(row.at)).toISOString(),
327109
+ principalActorId: row.principal_actor_id,
327110
+ actorId: row.actor_id,
327111
+ action: row.action,
327112
+ ...row.subject_id ? { subjectId: row.subject_id } : {},
327113
+ ...row.chat_session_id ? { chatSessionId: row.chat_session_id } : {},
327114
+ candidates: row.candidates,
327115
+ minScore: Number(row.min_score)
327116
+ }));
327117
+ }
327118
+ };
327119
+
327120
+ // ../server/src/domains/overlap/store.ts
327121
+ var import_node_crypto102 = require("node:crypto");
327122
+ var import_promises24 = require("node:fs/promises");
327123
+ var import_node_path36 = require("node:path");
327124
+ var MemoryOverlapEventStore = class _MemoryOverlapEventStore {
327125
+ constructor(filename) {
327126
+ this.filename = filename;
327127
+ }
327128
+ rows = [];
327129
+ tail = Promise.resolve();
327130
+ static async open(filename) {
327131
+ const store = new _MemoryOverlapEventStore(filename);
327132
+ try {
327133
+ store.rows = JSON.parse(await (0, import_promises24.readFile)(filename, "utf8"));
327134
+ } catch (error3) {
327135
+ if (error3.code !== "ENOENT") throw error3;
327136
+ }
327137
+ return store;
327138
+ }
327139
+ append(event) {
327140
+ const pending = this.tail.then(async () => {
327141
+ const next = [...this.rows, structuredClone(event)];
327142
+ if (this.filename) {
327143
+ await (0, import_promises24.mkdir)((0, import_node_path36.dirname)(this.filename), { recursive: true });
327144
+ const temp = `${this.filename}.${(0, import_node_crypto102.randomUUID)()}.tmp`;
327145
+ await (0, import_promises24.writeFile)(temp, JSON.stringify(next), "utf8");
327146
+ await (0, import_promises24.rename)(temp, this.filename);
327147
+ }
327148
+ this.rows = next;
327149
+ });
327150
+ this.tail = pending.catch(() => void 0);
327151
+ return pending;
327152
+ }
327153
+ async listRecent(limit) {
327154
+ await this.tail;
327155
+ return [...this.rows].sort((a5, b6) => a5.at < b6.at ? 1 : a5.at > b6.at ? -1 : 0).slice(0, limit).map((e5) => structuredClone(e5));
327156
+ }
327157
+ };
327158
+
326515
327159
  // ../cli/src/rebuild-artifact-projections-per-company.ts
326516
327160
  init_src11();
326517
327161
  var DEFAULT_LOGGER = {
@@ -326568,7 +327212,7 @@ init_src5();
326568
327212
  init_chat_exit();
326569
327213
 
326570
327214
  // ../cli/src/chat-task-header.ts
326571
- var import_node_crypto101 = require("node:crypto");
327215
+ var import_node_crypto103 = require("node:crypto");
326572
327216
  init_src11();
326573
327217
  init_src();
326574
327218
  var BRAINSTORM_LEGACY_LINE = "\u8BF7\u76F4\u63A5\u56DE\u7B54\u7528\u6237\u95EE\u9898\u3002\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u5199\u5165\u7CFB\u7EDF\uFF0C\u5426\u5219\u4E0D\u8981\u521B\u5EFA\u6216\u4FEE\u6539 artifact\u3002";
@@ -326629,7 +327273,7 @@ function buildChatTurnPrompts(input) {
326629
327273
  };
326630
327274
  }
326631
327275
  function chatSystemPromptFingerprint(systemPrompt) {
326632
- return (0, import_node_crypto101.createHash)("sha256").update(systemPrompt ?? "").digest("hex").slice(0, 16);
327276
+ return (0, import_node_crypto103.createHash)("sha256").update(systemPrompt ?? "").digest("hex").slice(0, 16);
326633
327277
  }
326634
327278
 
326635
327279
  // ../cli/src/chat-task-md.ts
@@ -327483,7 +328127,7 @@ function oasisWrapperScript() {
327483
328127
  const repoRoot = (0, import_node_url7.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
327484
328128
  const tsx = path32.join(repoRoot, "node_modules/.bin/tsx");
327485
328129
  const main = path32.join(repoRoot, "packages/cli/src/main.ts");
327486
- const key2 = (0, import_node_crypto102.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
328130
+ const key2 = (0, import_node_crypto104.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
327487
328131
  const uid = typeof process.getuid === "function" ? process.getuid() : "na";
327488
328132
  const stable = path32.join(os9.tmpdir(), `oasis-cli-wrapper-${uid}-${key2}`);
327489
328133
  let dir;
@@ -327911,7 +328555,7 @@ async function startServe(opts) {
327911
328555
  if (!hub) return Promise.resolve({ ok: false, reason: "\u672C\u8FDB\u7A0B\u6CA1\u6709\u8282\u70B9\u7F51\u5173" });
327912
328556
  const online = hub.connectedDaemons().some((d5) => d5.daemonId === nodeId);
327913
328557
  if (!online) return Promise.resolve({ ok: false, reason: "\u8282\u70B9\u5F53\u524D\u4E0D\u5728\u7EBF\uFF0C\u7528\u7684\u662F\u5B83\u4E0A\u6B21\u62A5\u7684\u6E05\u5355" });
327914
- const requestId = (0, import_node_crypto102.randomUUID)();
328558
+ const requestId = (0, import_node_crypto104.randomUUID)();
327915
328559
  const task = new Promise((resolve13) => {
327916
328560
  const timer = setTimeout(() => {
327917
328561
  modelRefreshWaiters.delete(requestId);
@@ -328760,7 +329404,7 @@ async function startServe(opts) {
328760
329404
  const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
328761
329405
  if (buf || session.runId) {
328762
329406
  await turnStore.appendMessage({
328763
- id: (0, import_node_crypto102.randomUUID)(),
329407
+ id: (0, import_node_crypto104.randomUUID)(),
328764
329408
  sessionId: chatSessionId,
328765
329409
  role: "assistant",
328766
329410
  content: buf,
@@ -328806,7 +329450,7 @@ async function startServe(opts) {
328806
329450
  chatTargets: {
328807
329451
  inspect: inspectChatTarget,
328808
329452
  createTargetSession: async ({ companyId, agentId, ownerHumanActorId, title }) => {
328809
- const sessionId = (0, import_node_crypto102.randomUUID)();
329453
+ const sessionId = (0, import_node_crypto104.randomUUID)();
328810
329454
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
328811
329455
  const binding = await registryStore.getBinding(agentId).catch(() => null);
328812
329456
  await (await chatStoreFor(companyId)).createSession({
@@ -329976,7 +330620,7 @@ async function startServe(opts) {
329976
330620
  onQuotaExhausted: (t) => {
329977
330621
  const daemon = hub?.connectedDaemons().find((d5) => d5.daemonId === t.nodeId);
329978
330622
  if (!daemon?.meta.supportsQuotaRefresh) return;
329979
- hub?.dispatch(t.nodeId, { type: "refresh_quotas", requestId: (0, import_node_crypto102.randomUUID)() });
330623
+ hub?.dispatch(t.nodeId, { type: "refresh_quotas", requestId: (0, import_node_crypto104.randomUUID)() });
329980
330624
  },
329981
330625
  actorName: async (actorId) => (await (await actors.resolveCtx(companyId)).service.getActor(actorId).catch(() => null))?.name ?? null
329982
330626
  });
@@ -330092,17 +330736,18 @@ async function startServe(opts) {
330092
330736
  warn: (error3) => console.warn(`[discussions] ${String(error3)}`)
330093
330737
  });
330094
330738
  const todoStores = /* @__PURE__ */ new Map();
330739
+ const todoStoreFor = (companyId) => {
330740
+ let store = todoStores.get(companyId);
330741
+ if (!store) {
330742
+ store = pgPool ? PostgresTodoStore.open(pgPool, engineSchemaFor(companyId)) : MemoryTodoStore.open(path32.join(opts.dir, "companies", companyEngineDirName(companyId), "todos.json"));
330743
+ todoStores.set(companyId, store);
330744
+ void store.catch(() => todoStores.delete(companyId));
330745
+ }
330746
+ return store;
330747
+ };
330095
330748
  const todoRuntime = createTodoRuntime({
330096
330749
  companies: async () => (await controlPlaneStore.listCompanies()).filter((c5) => c5.status === "active").map((c5) => c5.id),
330097
- store: (companyId) => {
330098
- let store = todoStores.get(companyId);
330099
- if (!store) {
330100
- store = pgPool ? PostgresTodoStore.open(pgPool, engineSchemaFor(companyId)) : MemoryTodoStore.open(path32.join(opts.dir, "companies", companyEngineDirName(companyId), "todos.json"));
330101
- todoStores.set(companyId, store);
330102
- void store.catch(() => todoStores.delete(companyId));
330103
- }
330104
- return store;
330105
- },
330750
+ store: todoStoreFor,
330106
330751
  timeZone: (companyId) => companies.service.effectiveTimeZoneOf(companyId),
330107
330752
  boundHuman: async (agentId, companyId) => (await (await resolveAssistantsCtx(companyId)).service.getByAgent(agentId))?.humanActorId ?? null,
330108
330753
  notifications: (companyId) => notificationStoreFor(companyId),
@@ -330122,6 +330767,31 @@ async function startServe(opts) {
330122
330767
  defaultCompanyId: () => defaultCompanyId,
330123
330768
  warn: (error3) => console.warn(`[todos] ${String(error3)}`)
330124
330769
  });
330770
+ const overlapEventStores = /* @__PURE__ */ new Map();
330771
+ const overlapRuntime = createOverlapRuntime({
330772
+ todos: todoStoreFor,
330773
+ workorderModel: async (companyId) => (await getEngine(companyId)).kernel.model,
330774
+ delegations: (companyId) => delegationStoreFor(companyId),
330775
+ people: async (companyId) => (await companies.service.listMemberViews(companyId)).map((m4) => ({
330776
+ actorId: m4.actorId,
330777
+ name: m4.displayName?.trim() || m4.name?.trim() || m4.email || m4.actorId
330778
+ })),
330779
+ actorName: async (companyId, actorId) => (await (await actors.resolveCtx(companyId)).service.getActor(actorId))?.name,
330780
+ sessionHuman: async (companyId, chatSessionId) => (await (await chatStoreFor(companyId)).getSession(chatSessionId))?.humanActorId,
330781
+ boundHuman: async (agentId, companyId) => (await (await resolveAssistantsCtx(companyId)).service.getByAgent(agentId))?.humanActorId ?? null,
330782
+ events: (companyId) => {
330783
+ let store = overlapEventStores.get(companyId);
330784
+ if (!store) {
330785
+ store = pgPool ? PostgresOverlapEventStore.open(pgPool, engineSchemaFor(companyId)) : MemoryOverlapEventStore.open(path32.join(opts.dir, "companies", companyEngineDirName(companyId), "overlap-events.json"));
330786
+ overlapEventStores.set(companyId, store);
330787
+ void store.catch(() => overlapEventStores.delete(companyId));
330788
+ }
330789
+ return store;
330790
+ },
330791
+ timeZone: (companyId) => companies.service.effectiveTimeZoneOf(companyId),
330792
+ defaultCompanyId: () => defaultCompanyId,
330793
+ warn: (error3) => console.warn(`[overlap] ${String(error3)}`)
330794
+ });
330125
330795
  const connectorRenewal = createConnectorRenewalRuntime({
330126
330796
  companies: async () => (await controlPlaneStore.listCompanies()).filter((c5) => c5.status === "active").map((c5) => c5.id),
330127
330797
  actors: async (companyId) => (await actors.resolveCtx(companyId)).service,
@@ -330360,7 +331030,7 @@ async function startServe(opts) {
330360
331030
  }));
330361
331031
  }
330362
331032
  const limits = { wallClockMs: wallClockForKind("planner") };
330363
- const artifactId = `artifact:planner:${(0, import_node_crypto102.randomUUID)()}`;
331033
+ const artifactId = `artifact:planner:${(0, import_node_crypto104.randomUUID)()}`;
330364
331034
  const handle = await chatRemoteAdapter.spawn({
330365
331035
  actor: planner.id,
330366
331036
  // companyId 同协调者:planner 用的就是默认公司的 actors 服务,漏签会让它一调公司域端点就 404。
@@ -330403,6 +331073,7 @@ async function startServe(opts) {
330403
331073
  projectsDomain2.register,
330404
331074
  discussionRuntime.register,
330405
331075
  todoRuntime.register,
331076
+ overlapRuntime.register,
330406
331077
  typesDomain({
330407
331078
  admin: typesAdmin,
330408
331079
  resolveAdmin: async (companyId) => {
@@ -331285,10 +331956,10 @@ async function startServe(opts) {
331285
331956
  if (isDeletedActor(dispatchTarget)) {
331286
331957
  throw new ApiError(409, ACTOR_DELETED_ERROR_CODE, ACTOR_DELETED_CHAT_MESSAGE);
331287
331958
  }
331288
- const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(retargetClaimedDispatch ? `chat-runtime:${requestDispatchId}:retry:${(0, import_node_crypto102.randomUUID)()}` : `chat-runtime:${requestDispatchId}`) : (0, import_node_crypto102.randomUUID)());
331959
+ const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(retargetClaimedDispatch ? `chat-runtime:${requestDispatchId}:retry:${(0, import_node_crypto104.randomUUID)()}` : `chat-runtime:${requestDispatchId}`) : (0, import_node_crypto104.randomUUID)());
331289
331960
  const resumeRuntimeSession = Boolean(sessionId);
331290
- const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0, import_node_crypto102.randomUUID)()}`;
331291
- const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto102.randomUUID)()}`;
331961
+ const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0, import_node_crypto104.randomUUID)()}`;
331962
+ const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto104.randomUUID)()}`;
331292
331963
  let stableDispatch = requestDispatchId ? await resolveStableChatDispatch({ store: await traceStoreFor(runCompanyId), runId: traceRunId }) : null;
331293
331964
  const retargetClaim = Boolean(retargetClaimedDispatch && stableDispatch && allocatedTurn);
331294
331965
  if (stableDispatch && !stableDispatch.shouldDispatch && !retargetClaim) {
@@ -332953,7 +333624,7 @@ async function startServe(opts) {
332953
333624
  console.log(`[new-engine] dispatchWork ${workId} \u662F human work\u2014\u2014\u4E0D\u6D3E runtime\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406`);
332954
333625
  return;
332955
333626
  }
332956
- const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0, import_node_crypto102.randomUUID)()}`;
333627
+ const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0, import_node_crypto104.randomUUID)()}`;
332957
333628
  try {
332958
333629
  const inserted = await (await dispatchLedgerFor(companyId)).insertOpen({
332959
333630
  id: ledgerId,
@@ -333053,7 +333724,7 @@ async function startServe(opts) {
333053
333724
  const kernelModel = newKernel.model;
333054
333725
  const art = kernelModel.artifacts.get(nodeId);
333055
333726
  const revWid = art?.workspace ?? "";
333056
- const ledgerId = `dispatch:${(0, import_node_crypto102.randomUUID)()}`;
333727
+ const ledgerId = `dispatch:${(0, import_node_crypto104.randomUUID)()}`;
333057
333728
  try {
333058
333729
  await (await dispatchLedgerFor(companyId)).insertOpen({
333059
333730
  id: ledgerId,
@@ -333424,7 +334095,7 @@ async function startServe(opts) {
333424
334095
  resolveSupplementalContext: server.knowledgeGovernance ? async ({ actorId, artifactId, workOrderId, action, part, runtimeKind, taskMarkdown }) => {
333425
334096
  try {
333426
334097
  const governance = server.knowledgeGovernance;
333427
- const taskFingerprint = (0, import_node_crypto102.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
334098
+ const taskFingerprint = (0, import_node_crypto104.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
333428
334099
  const requestContext = {
333429
334100
  organizationId: companyId,
333430
334101
  actorId,
@@ -335929,9 +336600,9 @@ function readCodexQuota(binary, signal, timeoutMs = 15e3) {
335929
336600
 
335930
336601
  // ../cli/src/daemon/quota/claude.ts
335931
336602
  var import_node_child_process18 = require("node:child_process");
335932
- var import_promises24 = require("node:fs/promises");
336603
+ var import_promises25 = require("node:fs/promises");
335933
336604
  var import_node_os14 = require("node:os");
335934
- var import_node_path36 = require("node:path");
336605
+ var import_node_path37 = require("node:path");
335935
336606
  var import_node_util5 = require("node:util");
335936
336607
  var exec = (0, import_node_util5.promisify)(import_node_child_process18.execFile);
335937
336608
  var USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
@@ -335950,9 +336621,9 @@ async function credentials(env2, signal) {
335950
336621
  }
335951
336622
  }
335952
336623
  if (!raw) {
335953
- const file = (0, import_node_path36.join)(env2.CLAUDE_CONFIG_DIR || (0, import_node_path36.join)((0, import_node_os14.homedir)(), ".claude"), ".credentials.json");
335954
- if ((await (0, import_promises24.stat)(file)).size > 256 * 1024) return void 0;
335955
- raw = await (0, import_promises24.readFile)(file, { encoding: "utf8", ...signal ? { signal } : {} });
336624
+ const file = (0, import_node_path37.join)(env2.CLAUDE_CONFIG_DIR || (0, import_node_path37.join)((0, import_node_os14.homedir)(), ".claude"), ".credentials.json");
336625
+ if ((await (0, import_promises25.stat)(file)).size > 256 * 1024) return void 0;
336626
+ raw = await (0, import_promises25.readFile)(file, { encoding: "utf8", ...signal ? { signal } : {} });
335956
336627
  }
335957
336628
  const oauth = object6(object6(JSON.parse(raw)).claudeAiOauth);
335958
336629
  if (typeof oauth.expiresAt === "number" && oauth.expiresAt <= Date.now()) return void 0;
@@ -336021,18 +336692,18 @@ async function readClaudeQuota(binary, signal, deps = {}) {
336021
336692
  }
336022
336693
 
336023
336694
  // ../cli/src/daemon/quota/shared-cache.ts
336024
- var import_node_crypto103 = require("node:crypto");
336695
+ var import_node_crypto105 = require("node:crypto");
336025
336696
  var import_node_fs27 = require("node:fs");
336026
336697
  var import_node_os15 = require("node:os");
336027
- var import_node_path37 = require("node:path");
336698
+ var import_node_path38 = require("node:path");
336028
336699
  init_src();
336029
336700
  function profileOf(kind, env2) {
336030
- if (kind === "codex") return `codex:${env2.CODEX_HOME || (0, import_node_path37.join)((0, import_node_os15.homedir)(), ".codex")}`;
336031
- if (env2.CLAUDE_CODE_OAUTH_TOKEN) return `claude-token:${(0, import_node_crypto103.createHash)("sha256").update(env2.CLAUDE_CODE_OAUTH_TOKEN).digest("hex")}`;
336032
- return `claude:${env2.CLAUDE_CONFIG_DIR || (0, import_node_path37.join)((0, import_node_os15.homedir)(), ".claude")}`;
336701
+ if (kind === "codex") return `codex:${env2.CODEX_HOME || (0, import_node_path38.join)((0, import_node_os15.homedir)(), ".codex")}`;
336702
+ if (env2.CLAUDE_CODE_OAUTH_TOKEN) return `claude-token:${(0, import_node_crypto105.createHash)("sha256").update(env2.CLAUDE_CODE_OAUTH_TOKEN).digest("hex")}`;
336703
+ return `claude:${env2.CLAUDE_CONFIG_DIR || (0, import_node_path38.join)((0, import_node_os15.homedir)(), ".claude")}`;
336033
336704
  }
336034
336705
  function fileQuotaCache(dir, env2 = process.env) {
336035
- const file = (kind) => (0, import_node_path37.join)(dir, `${kind}-${(0, import_node_crypto103.createHash)("sha256").update(profileOf(kind, env2)).digest("hex").slice(0, 16)}.json`);
336706
+ const file = (kind) => (0, import_node_path38.join)(dir, `${kind}-${(0, import_node_crypto105.createHash)("sha256").update(profileOf(kind, env2)).digest("hex").slice(0, 16)}.json`);
336036
336707
  return {
336037
336708
  get(kind) {
336038
336709
  try {
@@ -336214,7 +336885,7 @@ var RuntimeQuotaMonitor = class _RuntimeQuotaMonitor {
336214
336885
  init_wrapper();
336215
336886
  init_src();
336216
336887
  var import_node_os16 = require("node:os");
336217
- var import_node_crypto105 = require("node:crypto");
336888
+ var import_node_crypto107 = require("node:crypto");
336218
336889
  init_src3();
336219
336890
  init_src2();
336220
336891
 
@@ -336279,9 +336950,9 @@ function detectRuntimes() {
336279
336950
  }
336280
336951
 
336281
336952
  // ../cli/src/daemon/workdir-handler.ts
336282
- var import_node_crypto104 = require("node:crypto");
336953
+ var import_node_crypto106 = require("node:crypto");
336283
336954
  var import_node_fs28 = __toESM(require("node:fs"), 1);
336284
- var import_node_path38 = __toESM(require("node:path"), 1);
336955
+ var import_node_path39 = __toESM(require("node:path"), 1);
336285
336956
  init_src2();
336286
336957
  init_src();
336287
336958
  var WORKDIR_READ_MAX_BYTES = 2 * 1024 * 1024;
@@ -336302,10 +336973,10 @@ function isSensitiveSegment(segment) {
336302
336973
  }
336303
336974
  function relPathIsSensitive(rel) {
336304
336975
  if (!rel) return false;
336305
- return rel.split(import_node_path38.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
336976
+ return rel.split(import_node_path39.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
336306
336977
  }
336307
336978
  function withinBase(p4, base) {
336308
- return p4 === base || p4.startsWith(base + import_node_path38.default.sep);
336979
+ return p4 === base || p4.startsWith(base + import_node_path39.default.sep);
336309
336980
  }
336310
336981
  function normalizeRel(raw) {
336311
336982
  const trimmed = (raw ?? "").trim();
@@ -336322,7 +336993,7 @@ async function trustedCanonicalContainer(req, logicalBase, dirKind) {
336322
336993
  } catch {
336323
336994
  return null;
336324
336995
  }
336325
- return isLegacy ? import_node_path38.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path38.default.join(trustedRootReal, "sessions", dirKind);
336996
+ return isLegacy ? import_node_path39.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path39.default.join(trustedRootReal, "sessions", dirKind);
336326
336997
  }
336327
336998
  async function resolveWithinWorkdir(req) {
336328
336999
  const dirKind = sessionDirKind(req.runtimeKind);
@@ -336340,11 +337011,11 @@ async function resolveWithinWorkdir(req) {
336340
337011
  } catch {
336341
337012
  return { ok: false, code: "NOT_FOUND" };
336342
337013
  }
336343
- if (import_node_path38.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
337014
+ if (import_node_path39.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
336344
337015
  const rel = normalizeRel(req.path);
336345
- const requested = import_node_path38.default.resolve(base, rel);
337016
+ const requested = import_node_path39.default.resolve(base, rel);
336346
337017
  if (!withinBase(requested, base)) return { ok: false, code: "PATH_ESCAPE" };
336347
- const cleanRel = base === requested ? "" : import_node_path38.default.relative(base, requested);
337018
+ const cleanRel = base === requested ? "" : import_node_path39.default.relative(base, requested);
336348
337019
  if (relPathIsSensitive(cleanRel)) return { ok: false, code: "SENSITIVE" };
336349
337020
  let real;
336350
337021
  try {
@@ -336354,7 +337025,7 @@ async function resolveWithinWorkdir(req) {
336354
337025
  return { ok: false, code: "PATH_ESCAPE" };
336355
337026
  }
336356
337027
  if (!withinBase(real, base)) return { ok: false, code: "PATH_ESCAPE" };
336357
- const realRel = base === real ? "" : import_node_path38.default.relative(base, real);
337028
+ const realRel = base === real ? "" : import_node_path39.default.relative(base, real);
336358
337029
  if (relPathIsSensitive(realRel)) return { ok: false, code: "SENSITIVE" };
336359
337030
  return { ok: true, base, real };
336360
337031
  }
@@ -336390,7 +337061,7 @@ async function handleWorkdirList(req) {
336390
337061
  const slice = truncated ? visible.slice(0, WORKDIR_LIST_MAX_ENTRIES) : visible;
336391
337062
  const entries = [];
336392
337063
  for (const d5 of slice) {
336393
- const abs = import_node_path38.default.join(anchor, d5.name);
337064
+ const abs = import_node_path39.default.join(anchor, d5.name);
336394
337065
  try {
336395
337066
  const st = await import_node_fs28.default.promises.lstat(abs);
336396
337067
  if (st.isSymbolicLink()) continue;
@@ -336457,7 +337128,7 @@ async function verifyOpenedFd(fh, base, fallback2) {
336457
337128
  const fdReal = await fdCanonicalPath(fh);
336458
337129
  if (fdReal === null) return { anchor: fallback2 };
336459
337130
  if (!withinBase(fdReal, base)) return { error: { ok: false, code: "PATH_ESCAPE" } };
336460
- const fdRel = base === fdReal ? "" : import_node_path38.default.relative(base, fdReal);
337131
+ const fdRel = base === fdReal ? "" : import_node_path39.default.relative(base, fdReal);
336461
337132
  if (relPathIsSensitive(fdRel)) return { error: { ok: false, code: "SENSITIVE" } };
336462
337133
  return { anchor: `/proc/self/fd/${fh.fd}` };
336463
337134
  }
@@ -336528,7 +337199,7 @@ async function handleWorkdirHash(req) {
336528
337199
  const maxBytes = req.maxBytes ?? WORKDIR_READ_MAX_BYTES;
336529
337200
  return withVerifiedRegularFile(req, async (fh, st) => {
336530
337201
  if (st.size > maxBytes) return { ok: false, code: "TOO_LARGE", size: st.size };
336531
- const hash3 = (0, import_node_crypto104.createHash)("sha256");
337202
+ const hash3 = (0, import_node_crypto106.createHash)("sha256");
336532
337203
  const buf = Buffer.allocUnsafe(WORKDIR_HASH_CHUNK_BYTES);
336533
337204
  let total = 0;
336534
337205
  for (; ; ) {
@@ -336578,7 +337249,7 @@ function looksBinary(bytes2) {
336578
337249
  function contentTypeFor(absPath, bytes2) {
336579
337250
  const sniffed = sniffContentType(bytes2);
336580
337251
  if (sniffed) return sniffed;
336581
- const ext = import_node_path38.default.extname(absPath).toLowerCase();
337252
+ const ext = import_node_path39.default.extname(absPath).toLowerCase();
336582
337253
  if (EXT_CONTENT_TYPE[ext]) return EXT_CONTENT_TYPE[ext];
336583
337254
  return looksBinary(bytes2) ? "application/octet-stream" : "text/plain; charset=utf-8";
336584
337255
  }
@@ -337173,7 +337844,7 @@ var DaemonWsClient = class {
337173
337844
  */
337174
337845
  async queryArtifactStates(artifactIds, timeoutMs = 15e3) {
337175
337846
  if (artifactIds.length === 0) return {};
337176
- const requestId = (0, import_node_crypto105.randomUUID)();
337847
+ const requestId = (0, import_node_crypto107.randomUUID)();
337177
337848
  return new Promise((resolve13, reject) => {
337178
337849
  const timer = setTimeout(() => {
337179
337850
  this.gcPending.delete(requestId);
@@ -337355,17 +338026,17 @@ var RuntimeRouterAdapter = class {
337355
338026
  // ../cli/src/daemon/reap-claude-projects.ts
337356
338027
  var import_node_fs29 = __toESM(require("node:fs"), 1);
337357
338028
  var import_node_os17 = __toESM(require("node:os"), 1);
337358
- var import_node_path39 = __toESM(require("node:path"), 1);
338029
+ var import_node_path40 = __toESM(require("node:path"), 1);
337359
338030
  function claudeProjectSlug(cwd) {
337360
338031
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
337361
338032
  }
337362
338033
  function claudeProjectsRoot() {
337363
- const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path39.default.join(import_node_os17.default.homedir(), ".claude");
337364
- return import_node_path39.default.join(configDir, "projects");
338034
+ const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path40.default.join(import_node_os17.default.homedir(), ".claude");
338035
+ return import_node_path40.default.join(configDir, "projects");
337365
338036
  }
337366
338037
  function reapClaudeProjects(workdir, runtimeKind) {
337367
338038
  if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return;
337368
- const dir = import_node_path39.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
338039
+ const dir = import_node_path40.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
337369
338040
  if (!import_node_fs29.default.existsSync(dir)) return;
337370
338041
  try {
337371
338042
  import_node_fs29.default.rmSync(dir, { recursive: true, force: true });
@@ -337374,7 +338045,7 @@ function reapClaudeProjects(workdir, runtimeKind) {
337374
338045
  }
337375
338046
  function measureClaudeProjects(workdir, runtimeKind) {
337376
338047
  if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return 0;
337377
- const dir = import_node_path39.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
338048
+ const dir = import_node_path40.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
337378
338049
  return dirSizeBytes2(dir);
337379
338050
  }
337380
338051
  function dirSizeBytes2(dir) {
@@ -337386,7 +338057,7 @@ function dirSizeBytes2(dir) {
337386
338057
  return 0;
337387
338058
  }
337388
338059
  for (const e5 of entries) {
337389
- const p4 = import_node_path39.default.join(dir, e5.name);
338060
+ const p4 = import_node_path40.default.join(dir, e5.name);
337390
338061
  if (e5.isSymbolicLink()) continue;
337391
338062
  if (e5.isDirectory()) {
337392
338063
  total += dirSizeBytes2(p4);
@@ -337403,7 +338074,7 @@ function dirSizeBytes2(dir) {
337403
338074
  // ../cli/src/node.ts
337404
338075
  init_src2();
337405
338076
  var import_node_os18 = __toESM(require("node:os"), 1);
337406
- var import_node_path40 = __toESM(require("node:path"), 1);
338077
+ var import_node_path41 = __toESM(require("node:path"), 1);
337407
338078
  var idleFor = (runtimeKind) => CODE_DEFAULT_POLICY.resolve({ executor: "agent", scenario: "runtime-idle", runtimeKind }).idleTimeoutMs ?? 0;
337408
338079
  var RESILIENCE = {
337409
338080
  codex: { idleTimeoutMs: idleFor("codex") }
@@ -337475,7 +338146,7 @@ async function startNode(opts) {
337475
338146
  const client = new DaemonWsClient(opts.serverUrl, opts.nodeId, sessions, adapters, opts.token, runtimes, opts.nodeName, opts.reportRuntimes ?? false, true, opts.onUpdate, opts.daemonVersion, {
337476
338147
  ...opts.daemonPkg ? { daemonPkg: opts.daemonPkg } : {},
337477
338148
  // 同一个 OS 用户下的所有实例(~/.oasis/instances/*)共用一份额度采集结果:同账号 5 分钟只问一次上游。
337478
- quotaCacheDir: import_node_path40.default.join(import_node_os18.default.homedir(), ".oasis", "quota-cache"),
338149
+ quotaCacheDir: import_node_path41.default.join(import_node_os18.default.homedir(), ".oasis", "quota-cache"),
337479
338150
  // chat 文件浏览 handler 用它定位会话目录;production 不传 = 与 adapter 同款默认根(~/.oasis/work)。
337480
338151
  ...opts.workRoot !== void 0 ? { workRoot: opts.workRoot } : {},
337481
338152
  ...opts.spawnSessionProcess ? { spawnSessionProcess: opts.spawnSessionProcess } : {},
@@ -337594,7 +338265,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
337594
338265
  // ../cli/src/daemon/machine-id.ts
337595
338266
  var import_node_child_process20 = require("node:child_process");
337596
338267
  var import_node_fs30 = require("node:fs");
337597
- var import_node_crypto106 = require("node:crypto");
338268
+ var import_node_crypto108 = require("node:crypto");
337598
338269
  var import_node_os19 = require("node:os");
337599
338270
  function linuxMachineId() {
337600
338271
  for (const p4 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
@@ -337660,7 +338331,7 @@ var defaultSources = {
337660
338331
  function resolveNodeId(sources = {}) {
337661
338332
  const s3 = { ...defaultSources, ...sources };
337662
338333
  const material = `${s3.machineFingerprint()}:${s3.osUser()}`;
337663
- const digest3 = (0, import_node_crypto106.createHash)("sha256").update(material).digest("hex").slice(0, 12);
338334
+ const digest3 = (0, import_node_crypto108.createHash)("sha256").update(material).digest("hex").slice(0, 12);
337664
338335
  return `node-${digest3}`;
337665
338336
  }
337666
338337
 
@@ -337962,8 +338633,8 @@ var COMMAND_DECLS = {
337962
338633
  },
337963
338634
  delegate: {
337964
338635
  group: "\u59D4\u6D3E\u4E13\u5BB6",
337965
- usage: 'oasis delegate --to <role|actorId> --task "<\u4EFB\u52A1\u4E66>" [--as <\u77ED\u540D>] [--file <\u8DEF\u5F84>]... [--json true]\n oasis delegate --follow-up <\u5F15\u7528> --text "<...>" [--file <\u8DEF\u5F84>]...\n oasis delegate --status <\u5F15\u7528> [--json true]\n oasis delegate --list [--all] [--json true]',
337966
- description: "\u628A\u4E00\u4EF6\u4E8B\u4EA4\u7ED9\u7EC4\u7EC7\u91CC\u5BF9\u53E3\u7684\u4E13\u5BB6\u53BB\u505A\uFF08\u5F02\u6B65\uFF09\u3002\u547D\u4EE4\u7ACB\u5373\u8FD4\u56DE\uFF0C\u4E13\u5BB6\u5E72\u5B8C\u4E86\u7ED3\u679C\u81EA\u5DF1\u56DE\u5230\u8FD9\u6761\u5BF9\u8BDD\u2014\u2014**\u4E0D\u8981\u5728\u8FD9\u91CC\u7B49**\u3002",
338636
+ usage: 'oasis delegate --to <role|actorId> --task "<\u4EFB\u52A1\u4E66>" [--as <\u77ED\u540D>] [--file <\u8DEF\u5F84>]... [--json true]\n oasis delegate --follow-up <\u5F15\u7528> --text "<...>" [--file <\u8DEF\u5F84>]...\n oasis delegate --status <\u5F15\u7528|\u59D4\u6D3Eid> [--json true]\n oasis delegate --list [--all] [--json true]',
338637
+ description: "\u628A\u4E00\u4EF6\u4E8B\u4EA4\u7ED9\u7EC4\u7EC7\u91CC\u5BF9\u53E3\u7684\u4E13\u5BB6\u53BB\u505A\uFF08\u5F02\u6B65\uFF09\u3002\u547D\u4EE4\u7ACB\u5373\u8FD4\u56DE\uFF0C\u4E13\u5BB6\u5E72\u5B8C\u4E86\u7ED3\u679C\u81EA\u5DF1\u56DE\u5230\u8FD9\u6761\u5BF9\u8BDD\u2014\u2014**\u4E0D\u8981\u5728\u8FD9\u91CC\u7B49**\u3002\u6210\u529F\u540E\u5982\u679C\u672C\u516C\u53F8\u6709\u4EBA\u5728\u505A\u6216\u505A\u8FC7\u76F8\u8FD1\u7684\u4E8B\uFF0C\u8F93\u51FA\u672B\u5C3E\u4F1A\u591A\u4E00\u6BB5\u300C\u76F8\u8FD1\u7684\u4E8B\u9879\uFF08\u7CFB\u7EDF\u7C97\u7B5B\uFF0C\u672A\u786E\u8BA4\uFF0C\u8BF7\u7528 id \u67E5\u8BE6\u60C5\u540E\u5224\u65AD\uFF09\u300D\uFF0C\u6BCF\u6761\u5E26 id\uFF1A\u7528 id \u9010\u6761\u67E5\u8BE6\u60C5\uFF08\u5F85\u529E oasis todo show\u3001\u5DE5\u5355 oasis workorder\u3001\u59D4\u6D3E oasis delegate --status\uFF09\uFF0C\u5224\u65AD\u662F\u4E0D\u662F\u540C\u4E00\u4EF6\u4E8B\uFF1B\u786E\u5B9E\u76F8\u5173\u624D\u544A\u8BC9\u7528\u6237\uFF0C\u4E0D\u76F8\u5173\u4E00\u4E2A\u5B57\u90FD\u4E0D\u63D0\uFF1B\u5728\u505A\u7684\u5EFA\u8BAE\u7528\u6237\u5148\u95EE\u95EE\u5BF9\u65B9\uFF0C\u770B\u5408\u5E76\u8FD8\u662F\u5206\u5DE5\uFF1B\u505A\u5B8C\u7684\u628A\u7ED3\u679C\u7ED9\u7528\u6237\uFF0C\u95EE\u80FD\u4E0D\u80FD\u76F4\u63A5\u7528\uFF1B\u4E0D\u66FF\u7528\u6237\u505C\u6389\u8FD9\u6B21\u59D4\u6D3E\u3001\u5408\u5E76\u3001\u53D6\u6D88\u6216\u6539\u6D3E\u3002\u6CA1\u6709\u8FD9\u4E00\u6BB5\u5C31\u662F\u6CA1\u6BD4\u51FA\u6765\uFF0C\u6BD4\u5BF9\u51FA\u4E86\u95EE\u9898\u4E5F\u53EA\u662F\u6CA1\u6709\u8FD9\u4E00\u6BB5\uFF0C\u547D\u4EE4\u7167\u6837\u7B97\u6210\u529F\u3002",
337967
338638
  flags: [
337968
338639
  { name: "to", desc: "\u6D3E\u7ED9\u8C01\uFF1A\u5C97\u4F4D\u540D\u6216 actorId\uFF08\u5C97\u4F4D 0 \u4EBA\u5728\u5C97 / \u7ED1\u5B9A\u4E0D\u53EF\u7528\u4F1A\u5F53\u573A\u62A5\u9519\uFF0C\u90A3\u65F6\u81EA\u5DF1\u505A\uFF09" },
337969
338640
  { name: "task", desc: "\u4EFB\u52A1\u4E66\u5168\u6587\u2014\u2014\u4E13\u5BB6**\u552F\u4E00**\u7684\u4E0A\u4E0B\u6587\u6765\u6E90\uFF0C\u5199\u5168\uFF1B\u4E0D\u8BBE\u957F\u5EA6\u4E0A\u9650\u3001\u4E0D\u622A\u65AD" },
@@ -337971,7 +338642,7 @@ var COMMAND_DECLS = {
337971
338642
  { name: "file", desc: "\u4E00\u8D77\u5E26\u8FC7\u53BB\u7684\u6587\u4EF6\uFF08\u4F60\u5DE5\u4F5C\u76EE\u5F55\u4E0B\u7684\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u53EF\u7ED9\u591A\u6B21\uFF1B\u5355\u4E2A \u22642MB\u3001\u4E00\u6B21 \u226420 \u4E2A / 20MB\uFF09" },
337972
338643
  { name: "follow-up", desc: "\u5F80\u5DF2\u6709\u59D4\u6D3E\u91CC\u518D\u8FFD\u95EE/\u8F6C\u8FBE\u4E00\u53E5\uFF1A\u7ED9 label / \u4E13\u5BB6\u540D / delegationId \u524D\u7F00" },
337973
338644
  { name: "text", desc: "\u8FFD\u95EE\u5185\u5BB9\uFF08\u914D --follow-up\uFF09\u3002\u6539\u65B9\u5411\u5C31\u660E\u8BF4\u300C\u6539\u65B9\u5411\u300D\uFF0C\u4E13\u5BB6\u4F1A\u81EA\u5DF1\u5224\u65AD\u8981\u4E0D\u8981\u653E\u5F03\u624B\u4E0A\u90A3\u6BB5\u3002**\u770B\u56DE\u6267**\uFF1A\u63D2\u8FDB\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E / \u8D77\u4E86\u65B0\u7684\u4E00\u8F6E / \u8FD8\u6392\u5728\u961F\u5217\u91CC\u2014\u2014\u6392\u961F\u65F6\u4E13\u5BB6\u8981\u7B49\u672C\u8F6E\u8DD1\u5B8C\u624D\u770B\u89C1\uFF0C\u8BE5\u8DDF\u7528\u6237\u8BF4\u4E00\u58F0" },
337974
- { name: "status", desc: "\u770B\u4E00\u4E2A\u59D4\u6D3E\u7684\u8BE6\u60C5\uFF1A\u5168\u91CF\u5404\u8F6E\u5C0F\u7ED3 + \u4EA7\u7269\u6E05\u5355" },
338645
+ { name: "status", desc: "\u770B\u4E00\u4E2A\u59D4\u6D3E\u7684\u8BE6\u60C5\uFF1A\u5168\u91CF\u5404\u8F6E\u5C0F\u7ED3 + \u4EA7\u7269\u6E05\u5355\u3002\u7ED9\u7684\u662F**\u5B8C\u6574\u59D4\u6D3E id** \u4E14\u4E0D\u662F\u672C\u6BB5\u5BF9\u8BDD\u6D3E\u51FA\u7684\uFF08\u6BD4\u5982\u300C\u76F8\u8FD1\u7684\u4E8B\u9879\u300D\u91CC\u522B\u4EBA\u6D3E\u7684\uFF09\uFF0C\u9000\u5230\u53EA\u8BFB\u6458\u8981\uFF1A\u4EFB\u52A1\u4E66\u3001\u72B6\u6001\u3001\u4E13\u5BB6\u3001\u5404\u8F6E\u5C0F\u7ED3\u3001\u4EA7\u51FA\u6587\u4EF6\u540D\u3001\u6D3E\u6D3B\u5BF9\u8BDD\u3001\u5B50\u4F1A\u8BDD\uFF08\u4E0D\u542B\u5B50\u4F1A\u8BDD\u8FC7\u7A0B\uFF0C\u4E0D\u80FD --follow-up\uFF09" },
337975
338646
  { name: "list", desc: "\u5217\u51FA\u8FD9\u6761\u5BF9\u8BDD\u6D3E\u51FA\u53BB\u7684\u6D3B\uFF1B\u9ED8\u8BA4\u53EA\u7ED9\u8FDB\u884C\u4E2D + \u6700\u8FD1 10 \u6761", boolean: true },
337976
338647
  { name: "all", desc: "\u914D --list\uFF1A\u8FDE\u5386\u53F2\u59D4\u6D3E\u4E00\u8D77\u5217", boolean: true },
337977
338648
  { name: "json", desc: "\u8F93\u51FA JSON" }
@@ -337981,7 +338652,8 @@ var COMMAND_DECLS = {
337981
338652
  'oasis delegate --to \u8BBE\u8BA1\u5E08 --task "\u6309\u8FD9\u5F20\u53C2\u8003\u56FE\u91CD\u753B" --file inputs/attachments/ref.png',
337982
338653
  'oasis delegate --follow-up \u767B\u5F55\u9875 --text "\u7528\u6237\u6539\u65B9\u5411\uFF1A\u4E3B\u8272\u6362\u6210\u7EFF\u8272\uFF08\u624B\u4E0A\u8FD9\u6BB5\u53EF\u80FD\u8981\u4F5C\u5E9F\uFF0C\u4F60\u81EA\u5DF1\u5224\u65AD\uFF09"',
337983
338654
  "oasis delegate --list",
337984
- "oasis delegate --status \u767B\u5F55\u9875"
338655
+ "oasis delegate --status \u767B\u5F55\u9875",
338656
+ "oasis delegate --status 3f6c2a1e-8b4d-4c55-9a2e-1d7f0b9c4e21"
337985
338657
  ]
337986
338658
  },
337987
338659
  "node-token": {
@@ -338007,7 +338679,7 @@ var COMMAND_DECLS = {
338007
338679
  "run-playbook": {
338008
338680
  group: "\u5DE5\u5355",
338009
338681
  usage: "oasis run-playbook <ref> --title <t> --description <t> [--manager <actorId>] [--project <projectId>] [--attach <path> [--attach-type <mime>]]... [--dispatch true | --hold true]",
338010
- description: "\u6309\u5267\u672C\u5EFA\u5355\u3002\u7F3A\u7701\u751F\u6210\u8349\u6848\uFF08\u5F85\u4EBA\u786E\u8BA4\uFF09\uFF1B--dispatch \u76F4\u63A5\u6D3E\u53D1\uFF1B--hold \u6682\u505C\u6D3E\u53D1\u3002",
338682
+ description: "\u6309\u5267\u672C\u5EFA\u5355\u3002\u7F3A\u7701\u751F\u6210\u8349\u6848\uFF08\u5F85\u4EBA\u786E\u8BA4\uFF09\uFF1B--dispatch \u76F4\u63A5\u6D3E\u53D1\uFF1B--hold \u6682\u505C\u6D3E\u53D1\u3002\u6210\u529F\u540E\u5982\u679C\u672C\u516C\u53F8\u6709\u4EBA\u5728\u505A\u6216\u505A\u8FC7\u76F8\u8FD1\u7684\u4E8B\uFF0C\u8F93\u51FA\u672B\u5C3E\u4F1A\u591A\u4E00\u6BB5\u300C\u76F8\u8FD1\u7684\u4E8B\u9879\uFF08\u7CFB\u7EDF\u7C97\u7B5B\uFF0C\u672A\u786E\u8BA4\uFF0C\u8BF7\u7528 id \u67E5\u8BE6\u60C5\u540E\u5224\u65AD\uFF09\u300D\uFF0C\u6BCF\u6761\u5E26 id\u2014\u2014\u9010\u6761\u67E5\u8BE6\u60C5\u518D\u5224\u65AD\u662F\u4E0D\u662F\u540C\u4E00\u4EF6\u4E8B\uFF0C\u786E\u5B9E\u76F8\u5173\u624D\u544A\u8BC9\u7528\u6237\uFF08\u89C1\u6280\u80FD\uFF09\uFF1B\u6CA1\u6709\u8FD9\u4E00\u6BB5\u5C31\u662F\u6CA1\u6BD4\u51FA\u6765\uFF0C\u6BD4\u5BF9\u51FA\u4E86\u95EE\u9898\u4E5F\u53EA\u662F\u6CA1\u6709\u8FD9\u4E00\u6BB5\uFF0C\u547D\u4EE4\u7167\u6837\u7B97\u6210\u529F\u3002",
338011
338683
  positional: [
338012
338684
  { name: "<ref>", required: true, desc: "\u5267\u672C\u5F15\u7528\u540D" }
338013
338685
  ],
@@ -339012,7 +339684,7 @@ var COMMAND_DECLS = {
339012
339684
  "create-workorder": {
339013
339685
  group: "\u5DE5\u5355",
339014
339686
  usage: "oasis create-workorder --type <t> --title <\u6807\u9898> [--brief <\u63CF\u8FF0>] [--workspace <ws>] [--owner <humanActorId>] [--dispatch true|false] [--attachment <\u672C\u5730\u6587\u4EF6> [--attach-type <mime>]]\u2026",
339015
- description: "\u5EFA\u5355 agent \u628A\u5BF9\u8BDD\u6572\u5B9A\u7684\u5DE5\u5355\u7ED3\u6784\u5316\u6682\u5B58\u6210\u8349\u6848\u3002--dispatch true \u8DF3\u8FC7\u8349\u6848\u76F4\u63A5\u5EFA\u771F\u5355\u5E76\u6D3E\u53D1\uFF1B--dispatch false \u843D\u8349\u6848\u5E76\u6807\u8BB0\u7A0D\u540E\u6D3E\u53D1\u3002--attachment \u53EF\u91CD\u590D\uFF0C\u5355\u6587\u4EF6 \u226410MB\u3001\u6700\u591A 20 \u4E2A\u3002",
339687
+ description: "\u5EFA\u5355 agent \u628A\u5BF9\u8BDD\u6572\u5B9A\u7684\u5DE5\u5355\u7ED3\u6784\u5316\u6682\u5B58\u6210\u8349\u6848\u3002--dispatch true \u8DF3\u8FC7\u8349\u6848\u76F4\u63A5\u5EFA\u771F\u5355\u5E76\u6D3E\u53D1\uFF1B--dispatch false \u843D\u8349\u6848\u5E76\u6807\u8BB0\u7A0D\u540E\u6D3E\u53D1\u3002--attachment \u53EF\u91CD\u590D\uFF0C\u5355\u6587\u4EF6 \u226410MB\u3001\u6700\u591A 20 \u4E2A\u3002\u6210\u529F\u540E\u5982\u679C\u672C\u516C\u53F8\u6709\u4EBA\u5728\u505A\u6216\u505A\u8FC7\u76F8\u8FD1\u7684\u4E8B\uFF0C\u8F93\u51FA\u672B\u5C3E\u4F1A\u591A\u4E00\u6BB5\u300C\u76F8\u8FD1\u7684\u4E8B\u9879\uFF08\u7CFB\u7EDF\u7C97\u7B5B\uFF0C\u672A\u786E\u8BA4\uFF0C\u8BF7\u7528 id \u67E5\u8BE6\u60C5\u540E\u5224\u65AD\uFF09\u300D\uFF0C\u6BCF\u6761\u5E26 id\u2014\u2014\u9010\u6761\u67E5\u8BE6\u60C5\u518D\u5224\u65AD\u662F\u4E0D\u662F\u540C\u4E00\u4EF6\u4E8B\uFF0C\u786E\u5B9E\u76F8\u5173\u624D\u544A\u8BC9\u7528\u6237\uFF08\u89C1\u6280\u80FD\uFF09\uFF1B\u6CA1\u6709\u8FD9\u4E00\u6BB5\u5C31\u662F\u6CA1\u6BD4\u51FA\u6765\uFF0C\u6BD4\u5BF9\u51FA\u4E86\u95EE\u9898\u4E5F\u53EA\u662F\u6CA1\u6709\u8FD9\u4E00\u6BB5\uFF0C\u547D\u4EE4\u7167\u6837\u7B97\u6210\u529F\u3002",
339016
339688
  flags: [
339017
339689
  { name: "type", desc: "\u6839\u4EA7\u7269\u7C7B\u578B", required: true },
339018
339690
  { name: "title", desc: "\u5DE5\u5355\u6807\u9898", required: true },
@@ -339408,7 +340080,7 @@ var COMMAND_DECLS = {
339408
340080
  "todo add": {
339409
340081
  group: "\u4E2A\u4EBA\u5F85\u529E",
339410
340082
  usage: "oasis todo add [--to <\u4EBA>] --title <\u4E00\u53E5\u8BDD\uFF0C\u52A8\u8BCD\u5F00\u5934> [--note <\u8C01\u8981\u3001\u4E3A\u4EC0\u4E48\u3001\u539F\u8BDD\u8981\u70B9>] [--start YYYY-MM-DD [--start-time HH:mm]] --due YYYY-MM-DD [--time HH:mm]",
339411
- description: "\u8BB0\u4E00\u6761\u5F85\u529E\u3002--due / --start \u53EA\u6536\u4E0D\u5E26\u65F6\u533A\u7684\u65E5\u671F\uFF08\u7EC4\u7EC7\u65F6\u533A\u91CC\u7684\u90A3\u4E00\u5929\uFF09\uFF0C\u975E\u6CD5\u65E5\u671F\u5F53\u573A\u62A5\u9519\uFF1B\u6CA1\u8BF4\u51E0\u70B9\u5C31\u522B\u7ED9 --time\uFF1B\u7528\u6237\u6CA1\u8BF4\u4EC0\u4E48\u65F6\u5019\u5F00\u59CB\u5C31\u522B\u7ED9 --start\uFF08\u4E0D\u8FFD\u95EE\u3001\u4E0D\u731C\uFF09\uFF0C\u5F00\u59CB\u4E0D\u80FD\u665A\u4E8E\u622A\u6B62\u3002\u6765\u6E90\u5BF9\u8BDD\u81EA\u52A8\u53D6 $OASIS_CHAT_SESSION_ID\uFF08\u63D0\u9192\u70B9\u5F00\u4F1A\u8DF3\u56DE\u8FD9\u91CC\uFF09\u3002\u7ED9\u81EA\u5DF1\u8BB0\uFF1A\u6210\u529F\u8F93\u51FA\u300C\u8BB0\u4E0B\u4E86\uFF1A<\u6807\u9898>\uFF0C\u622A\u6B62 X \u6708 X \u65E5\uFF08\u5468X\uFF09\u300D\u3002--to \u6D3E\u7ED9\u522B\u4EBA\uFF1A\u53EA\u5B58\u6210**\u8349\u6848**\uFF0C\u8F93\u51FA\u300C\u8349\u6848\uFF08\u8FD8\u6CA1\u53D1\u51FA\uFF09\uFF1A\u6D3E\u7ED9 X\uFF1A\u2026\u300D\uFF0C\u5BF9\u8BDD\u91CC\u51FA\u4E00\u5F20\u8349\u6848\u5361\uFF0C\u7528\u6237\u70B9\u300C\u53D1\u51FA\u300D\u624D\u751F\u6548\u3001\u5BF9\u65B9\u624D\u6536\u5230\u901A\u77E5\u2014\u2014\u4F60\u4E0D\u80FD\u66FF TA \u53D1\u51FA\u3002--to \u8BA4 actorId \u6216\u540D\u5B57\uFF0C\u5BF9\u4E0D\u4E0A\u6216\u5BF9\u4E0A\u4E0D\u6B62\u4E00\u4E2A\u76F4\u63A5\u62A5\u9519\uFF0C\u522B\u731C\uFF0C\u95EE\u7528\u6237\u662F\u54EA\u4F4D\u3002",
340083
+ description: "\u8BB0\u4E00\u6761\u5F85\u529E\u3002--due / --start \u53EA\u6536\u4E0D\u5E26\u65F6\u533A\u7684\u65E5\u671F\uFF08\u7EC4\u7EC7\u65F6\u533A\u91CC\u7684\u90A3\u4E00\u5929\uFF09\uFF0C\u975E\u6CD5\u65E5\u671F\u5F53\u573A\u62A5\u9519\uFF1B\u6CA1\u8BF4\u51E0\u70B9\u5C31\u522B\u7ED9 --time\uFF1B\u7528\u6237\u6CA1\u8BF4\u4EC0\u4E48\u65F6\u5019\u5F00\u59CB\u5C31\u522B\u7ED9 --start\uFF08\u4E0D\u8FFD\u95EE\u3001\u4E0D\u731C\uFF09\uFF0C\u5F00\u59CB\u4E0D\u80FD\u665A\u4E8E\u622A\u6B62\u3002\u6765\u6E90\u5BF9\u8BDD\u81EA\u52A8\u53D6 $OASIS_CHAT_SESSION_ID\uFF08\u63D0\u9192\u70B9\u5F00\u4F1A\u8DF3\u56DE\u8FD9\u91CC\uFF09\u3002\u7ED9\u81EA\u5DF1\u8BB0\uFF1A\u6210\u529F\u8F93\u51FA\u300C\u8BB0\u4E0B\u4E86\uFF1A<\u6807\u9898>\uFF0C\u622A\u6B62 X \u6708 X \u65E5\uFF08\u5468X\uFF09\u300D\u3002--to \u6D3E\u7ED9\u522B\u4EBA\uFF1A\u53EA\u5B58\u6210**\u8349\u6848**\uFF0C\u8F93\u51FA\u300C\u8349\u6848\uFF08\u8FD8\u6CA1\u53D1\u51FA\uFF09\uFF1A\u6D3E\u7ED9 X\uFF1A\u2026\u300D\uFF0C\u5BF9\u8BDD\u91CC\u51FA\u4E00\u5F20\u8349\u6848\u5361\uFF0C\u7528\u6237\u70B9\u300C\u53D1\u51FA\u300D\u624D\u751F\u6548\u3001\u5BF9\u65B9\u624D\u6536\u5230\u901A\u77E5\u2014\u2014\u4F60\u4E0D\u80FD\u66FF TA \u53D1\u51FA\u3002--to \u8BA4 actorId \u6216\u540D\u5B57\uFF0C\u5BF9\u4E0D\u4E0A\u6216\u5BF9\u4E0A\u4E0D\u6B62\u4E00\u4E2A\u76F4\u63A5\u62A5\u9519\uFF0C\u522B\u731C\uFF0C\u95EE\u7528\u6237\u662F\u54EA\u4F4D\u3002\u6210\u529F\u540E\u5982\u679C\u672C\u516C\u53F8\u6709\u4EBA\u5728\u505A\u6216\u505A\u8FC7\u76F8\u8FD1\u7684\u4E8B\uFF0C\u8F93\u51FA\u672B\u5C3E\u4F1A\u591A\u4E00\u6BB5\u300C\u76F8\u8FD1\u7684\u4E8B\u9879\uFF08\u7CFB\u7EDF\u7C97\u7B5B\uFF0C\u672A\u786E\u8BA4\uFF0C\u8BF7\u7528 id \u67E5\u8BE6\u60C5\u540E\u5224\u65AD\uFF09\u300D\uFF0C\u6BCF\u6761\u5E26 id\u2014\u2014\u9010\u6761\u67E5\u8BE6\u60C5\u518D\u5224\u65AD\u662F\u4E0D\u662F\u540C\u4E00\u4EF6\u4E8B\uFF0C\u786E\u5B9E\u76F8\u5173\u624D\u544A\u8BC9\u7528\u6237\uFF08\u89C1\u6280\u80FD\uFF09\uFF1B\u6CA1\u6709\u8FD9\u4E00\u6BB5\u5C31\u662F\u6CA1\u6BD4\u51FA\u6765\uFF0C\u6BD4\u5BF9\u51FA\u4E86\u95EE\u9898\u4E5F\u53EA\u662F\u6CA1\u6709\u8FD9\u4E00\u6BB5\uFF0C\u547D\u4EE4\u7167\u6837\u7B97\u6210\u529F\u3002",
339412
340084
  flags: [
339413
340085
  { name: "to", desc: "\u6D3E\u7ED9\u8C01\uFF1A\u672C\u516C\u53F8\u771F\u4EBA\u7684 actorId \u6216\u540D\u5B57\uFF08\u4E0D\u7ED9 = \u7ED9\u81EA\u5DF1\u8BB0\uFF09", own: true },
339414
340086
  { name: "title", desc: "\u6807\u9898\uFF1A\u4E00\u53E5\u8BDD\u3001\u52A8\u8BCD\u5F00\u5934", required: true, own: true },
@@ -339439,13 +340111,13 @@ var COMMAND_DECLS = {
339439
340111
  "todo show": {
339440
340112
  group: "\u4E2A\u4EBA\u5F85\u529E",
339441
340113
  usage: "oasis todo show <id>",
339442
- description: "\u770B\u4E00\u6761\u5F85\u529E\u7684\u5168\u8C8C\uFF1A\u6807\u9898\u3001\u5F00\u59CB \u2192 \u622A\u6B62\u3001\u72B6\u6001\u3001\u53D1\u8D77\u4EBA\u3001\u627F\u63A5\u4EBA\uFF08\u6D3E\u7ED9\u522B\u4EBA\u7684\u8FD8\u6709\u53D1\u51FA\u65F6\u95F4\u3001\u627F\u63A5\u4EBA\u9996\u6B21\u67E5\u770B\u65F6\u95F4\uFF09\u3001\u5907\u6CE8\u5168\u6587\uFF0C\u4EE5\u53CA\u53D8\u66F4\u8BB0\u5F55\uFF08\u65F6\u95F4\u3001\u8C01\u6539\u7684 / \u7ECF\u624B agent\u3001\u5B57\u6BB5\u3001\u65E7\u503C \u2192 \u65B0\u503C\u3001\u539F\u56E0\uFF0C\u65B0\u7684\u5728\u524D\uFF09\u3002\u6539\u5907\u6CE8\u524D\u5148\u7528\u5B83\u8BFB\u51FA\u5F53\u524D\u5907\u6CE8\u5168\u6587\uFF1B\u7528\u6237\u95EE\u300C\u4E4B\u524D\u5199\u7684\u662F\u4EC0\u4E48\u300D\u4E5F\u67E5\u8FD9\u91CC\u3002\u672C\u516C\u53F8\u8C01\u7684\u5F85\u529E\u90FD\u80FD\u770B\uFF08\u522B\u4EBA\u7684\u8349\u6848\u9664\u5916\uFF09\uFF1B\u627F\u63A5\u4EBA\u7B2C\u4E00\u6B21\u770B\u4F1A\u88AB\u8BB0\u4E0B\u3002",
340114
+ description: "\u770B\u4E00\u6761\u5F85\u529E\u7684\u5168\u8C8C\uFF1A\u6807\u9898\u3001\u5F00\u59CB \u2192 \u622A\u6B62\u3001\u72B6\u6001\u3001\u53D1\u8D77\u4EBA\u3001\u627F\u63A5\u4EBA\uFF08\u6D3E\u7ED9\u522B\u4EBA\u7684\u8FD8\u6709\u53D1\u51FA\u65F6\u95F4\u3001\u627F\u63A5\u4EBA\u9996\u6B21\u67E5\u770B\u65F6\u95F4\uFF09\u3001\u7ED3\u679C\u5728\u54EA\uFF08\u5B8C\u6210\u65F6\u8BB0\u4E86\u7684\uFF09\u3001\u5907\u6CE8\u5168\u6587\uFF0C\u4EE5\u53CA\u53D8\u66F4\u8BB0\u5F55\uFF08\u65F6\u95F4\u3001\u8C01\u6539\u7684 / \u7ECF\u624B agent\u3001\u5B57\u6BB5\u3001\u65E7\u503C \u2192 \u65B0\u503C\u3001\u539F\u56E0\uFF0C\u65B0\u7684\u5728\u524D\uFF09\u3002\u6539\u5907\u6CE8\u524D\u5148\u7528\u5B83\u8BFB\u51FA\u5F53\u524D\u5907\u6CE8\u5168\u6587\uFF1B\u7528\u6237\u95EE\u300C\u4E4B\u524D\u5199\u7684\u662F\u4EC0\u4E48\u300D\u4E5F\u67E5\u8FD9\u91CC\u3002\u672C\u516C\u53F8\u8C01\u7684\u5F85\u529E\u90FD\u80FD\u770B\uFF08\u522B\u4EBA\u7684\u8349\u6848\u9664\u5916\uFF09\uFF1B\u627F\u63A5\u4EBA\u7B2C\u4E00\u6B21\u770B\u4F1A\u88AB\u8BB0\u4E0B\u3002",
339443
340115
  positional: [{ name: "<id>", required: true, desc: "\u5F85\u529E id\uFF08oasis todo list \u7B2C\u4E00\u5217\uFF09" }],
339444
340116
  examples: ["oasis todo show td_3f9a1c2b"]
339445
340117
  },
339446
340118
  "todo edit": {
339447
340119
  group: "\u4E2A\u4EBA\u5F85\u529E",
339448
- usage: "oasis todo edit <id> [--title \u2026] [--note \u2026] [--start YYYY-MM-DD|none] [--start-time HH:mm|none] [--due YYYY-MM-DD] [--time HH:mm|none] [--workorder <\u5DE5\u5355 id>|none] [--to <\u4EBA>] [--reason \u2026]",
340120
+ usage: "oasis todo edit <id> [--title \u2026] [--note \u2026] [--start YYYY-MM-DD|none] [--start-time HH:mm|none] [--due YYYY-MM-DD] [--time HH:mm|none] [--workorder <\u5DE5\u5355 id>|none] [--to <\u4EBA>] [--result <\u7ED3\u679C\u5728\u54EA>|none] [--reason \u2026]",
339449
340121
  description: '\u6539\u4E00\u6761\u5F85\u529E\u7684\u5B57\u6BB5\uFF0C\u7ED9\u4E86\u54EA\u4E2A\u6539\u54EA\u4E2A\uFF1B\u6BCF\u6539\u4E00\u4E2A\u5B57\u6BB5\u90FD\u7559\u4E00\u6761\u8BB0\u5F55\uFF08\u65E7\u503C\u3001\u65B0\u503C\u3001\u539F\u56E0\uFF09\u3002\u53EA\u6709\u53D1\u8D77\u4EBA\u548C\u627F\u63A5\u4EBA\u80FD\u6539\uFF1B\u6D3E\u7ED9\u522B\u4EBA\u4E14\u5DF2\u53D1\u51FA\u7684\uFF0C\u6539\u4E86\u4F1A\u901A\u77E5\u53E6\u4E00\u65B9\u3002\u6539\u671F\u8981\u5199\u539F\u56E0\uFF1A\u7528\u6237\u6CA1\u8BF4\u5C31\u95EE\u4E00\u53E5\uFF1B**\u522B\u4EBA\u6D3E\u7ED9\u4F60\u7684\u6539\u622A\u6B62\u5FC5\u987B\u5E26 --reason**\uFF08\u4E0D\u5E26\u76F4\u63A5\u62A5\u9519\uFF09\uFF0C\u81EA\u5DF1\u8BB0\u7684\u7528\u6237\u8BF4\u4E0D\u7528\u5C31\u4E0D\u5199\uFF0C\u522B\u7F16\u3002--to \u53EA\u80FD\u5728\u8FD8\u6CA1\u53D1\u51FA\u7684\u8349\u6848\u4E0A\u6362\u627F\u63A5\u4EBA\u3002--start none\uFF08\u8FDE\u540C\u5F00\u59CB\u65F6\u523B\uFF09/ --start-time none / --time none / --workorder none \u6E05\u7A7A\uFF0C--note "" \u6E05\u7A7A\u5907\u6CE8\u3002',
339450
340122
  positional: [{ name: "<id>", required: true, desc: "\u5F85\u529E id\uFF08oasis todo list \u7B2C\u4E00\u5217\uFF09" }],
339451
340123
  flags: [
@@ -339457,16 +340129,21 @@ var COMMAND_DECLS = {
339457
340129
  { name: "time", desc: "\u65B0\u622A\u6B62\u65F6\u523B HH:mm\uFF1Bnone = \u6E05\u7A7A", own: true },
339458
340130
  { name: "workorder", desc: "\u5173\u8054\u7684\u5DE5\u5355 id\uFF08\u300C\u8FD9\u4EF6\u4F60\u5E2E\u6211\u505A\u4E86\u5427\u300D\u5EFA\u5355\u540E\u6302\u4E0A\uFF09\uFF1Bnone = \u6E05\u7A7A", own: true },
339459
340131
  { name: "to", desc: "\u6362\u627F\u63A5\u4EBA\uFF08\u53EA\u9650\u8FD8\u6CA1\u53D1\u51FA\u7684\u8349\u6848\uFF09", own: true },
340132
+ { name: "result", desc: "\u7ED3\u679C\u5728\u54EA\uFF08\u6587\u4EF6 / \u94FE\u63A5 / \u5DE5\u5355 id\uFF09\uFF1A\u8865\u8BB0\u6216\u6539\u6B63\u5B8C\u6210\u65F6\u8BB0\u7684\u90A3\u53E5\uFF1Bnone = \u6E05\u7A7A", own: true },
339460
340133
  { name: "reason", desc: "\u4E3A\u4EC0\u4E48\u6539\uFF08\u6539\u671F\u65F6\u8981\u5199\uFF1B\u522B\u4EBA\u6D3E\u7ED9\u4F60\u7684\u6539\u622A\u6B62\u5FC5\u987B\u5199\uFF09", own: true }
339461
340134
  ],
339462
340135
  examples: ['oasis todo edit td_3f9a1c2b --due 2026-10-12 --reason "\u5BA2\u6237\u5EF6\u671F\u4E00\u5468"']
339463
340136
  },
339464
340137
  "todo done": {
339465
340138
  group: "\u4E2A\u4EBA\u5F85\u529E",
339466
- usage: "oasis todo done <id> [--reason \u2026]",
339467
- description: "\u6807\u8BB0\u5B8C\u6210\u3002\u5339\u914D\u5230\u591A\u6761\u65F6\u5148\u95EE\u7528\u6237\u662F\u54EA\u6761\uFF0C\u522B\u731C\u3002\u6D3E\u7ED9\u522B\u4EBA\u4E14\u5DF2\u53D1\u51FA\u7684\uFF0C\u5B8C\u6210\u540E\u901A\u77E5\u53E6\u4E00\u65B9\u3002",
340139
+ usage: "oasis todo done <id> [--result <\u6587\u4EF6 / \u94FE\u63A5 / \u5DE5\u5355 id>] [--reason \u2026]",
340140
+ description: "\u6807\u8BB0\u5B8C\u6210\u3002\u5339\u914D\u5230\u591A\u6761\u65F6\u5148\u95EE\u7528\u6237\u662F\u54EA\u6761\uFF0C\u522B\u731C\u3002\u6807\u4E4B\u524D\u987A\u53E3\u95EE\u4E00\u53E5\u300C\u7ED3\u679C\u5728\u54EA\uFF1F\u300D\uFF0C\u7528\u6237\u8BF4\u4E86\u5C31 --result \u8BB0\u4E0B\uFF08\u540C\u4E8B\u4EE5\u540E\u505A\u7C7B\u4F3C\u7684\u4E8B\uFF0C\u6BD4\u5BF9\u4F1A\u628A\u5B83\u5E26\u51FA\u6765\uFF09\uFF1B\u7528\u6237\u8BF4\u6CA1\u6709\u3001\u4E0D\u7528\u8BB0\u5C31\u4E0D\u7ED9 --result\uFF0C\u522B\u8FFD\u95EE\u3001\u522B\u7F16\u3002\u6D3E\u7ED9\u522B\u4EBA\u4E14\u5DF2\u53D1\u51FA\u7684\uFF0C\u5B8C\u6210\u540E\u901A\u77E5\u53E6\u4E00\u65B9\u3002",
339468
340141
  positional: [{ name: "<id>", required: true, desc: "\u5F85\u529E id" }],
339469
- flags: [{ name: "reason", desc: "\u5907\u6CE8\u4E00\u53E5\uFF08\u53EF\u9009\uFF09", own: true }]
340142
+ flags: [
340143
+ { name: "result", desc: "\u7ED3\u679C\u5728\u54EA\uFF1A\u6587\u4EF6\u8DEF\u5F84\u3001\u94FE\u63A5\u6216\u5DE5\u5355 id\uFF08\u53EF\u9009\uFF1B\u4E4B\u540E\u8981\u6539\u7528 todo edit --result\uFF09", own: true },
340144
+ { name: "reason", desc: "\u5907\u6CE8\u4E00\u53E5\uFF08\u53EF\u9009\uFF09", own: true }
340145
+ ],
340146
+ examples: ['oasis todo done td_3f9a1c2b --result "outputs/\u7ADE\u54C1\u62A5\u4EF7.xlsx"', "oasis todo done td_3f9a1c2b"]
339470
340147
  },
339471
340148
  "todo cancel": {
339472
340149
  group: "\u4E2A\u4EBA\u5F85\u529E",
@@ -339677,13 +340354,13 @@ function ownFlagsFromDecl(command6) {
339677
340354
  }
339678
340355
 
339679
340356
  // ../cli/src/connector-effect-runner.ts
339680
- var import_node_crypto107 = require("node:crypto");
340357
+ var import_node_crypto109 = require("node:crypto");
339681
340358
  var import_node_child_process21 = require("node:child_process");
339682
340359
  init_src3();
339683
340360
  function stableKey(effect) {
339684
340361
  const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a5], [b6]) => a5.localeCompare(b6)));
339685
340362
  const canonical2 = JSON.stringify({ kind: effect.kind, target: effect.target, keyFields });
339686
- return `sha256:${(0, import_node_crypto107.createHash)("sha256").update(canonical2).digest("hex")}`;
340363
+ return `sha256:${(0, import_node_crypto109.createHash)("sha256").update(canonical2).digest("hex")}`;
339687
340364
  }
339688
340365
  async function runConnectorEffect(connector, toolArgs, deps) {
339689
340366
  const effect = connector.describeExternalEffect?.(toolArgs) ?? null;
@@ -340169,6 +340846,8 @@ var ApiRequestError = class extends Error {
340169
340846
  this.name = "ApiRequestError";
340170
340847
  }
340171
340848
  };
340849
+ var OVERLAP_TIMEOUT_MS = 5e3;
340850
+ var DELEGATION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
340172
340851
  var CHAT_HISTORY_SPEAKER = { user: "\u7528\u6237", assistant: "\u52A9\u624B", system: "\u7CFB\u7EDF" };
340173
340852
  function renderChatHistory(view, search2) {
340174
340853
  const lines = [];
@@ -340252,7 +340931,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback2) {
340252
340931
  const timeoutMs = resolveAuthWaitMs();
340253
340932
  const controller = new AbortController();
340254
340933
  const timer = setTimeout(() => controller.abort(), timeoutMs);
340255
- const waiterId = (0, import_node_crypto108.randomUUID)();
340934
+ const waiterId = (0, import_node_crypto110.randomUUID)();
340256
340935
  process.stderr.write(
340257
340936
  `\u7B49\u5F85\u4EBA\u5DE5\u6388\u6743\u4E2D\u2026\u2026\u6700\u591A ${Math.round(timeoutMs / 1e3)} \u79D2\uFF0C\u8D85\u65F6\u4F1A\u81EA\u52A8\u8F6C\u4E3A\u5F85\u5BA1\uFF1B\u8FD9\u4E0D\u662F\u9519\u8BEF\uFF0C\u8BF7\u52FF\u91CD\u8BD5\u540C\u4E00\u6761\u547D\u4EE4\u3002
340258
340937
  `
@@ -340336,7 +341015,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback2) {
340336
341015
  }
340337
341016
  }
340338
341017
  }
340339
- var CLI_VERSION = "2.2.121" ? "2.2.121" : "dev";
341018
+ var CLI_VERSION = "2.2.123" ? "2.2.123" : "dev";
340340
341019
  function apiHeaders(token2, company) {
340341
341020
  const headers = {
340342
341021
  authorization: `Bearer ${token2}`,
@@ -340380,11 +341059,12 @@ function makeClient(base, token2, opts = {}) {
340380
341059
  if (!res.ok) await fail(res);
340381
341060
  return (await res.json()).data;
340382
341061
  },
340383
- async request(method, path50, body2) {
341062
+ async request(method, path50, body2, opts2) {
340384
341063
  const res = await fetch(`${base}${path50}`, {
340385
341064
  method,
340386
341065
  headers,
340387
- ...body2 !== void 0 ? { body: JSON.stringify(body2) } : {}
341066
+ ...body2 !== void 0 ? { body: JSON.stringify(body2) } : {},
341067
+ ...opts2?.timeoutMs ? { signal: AbortSignal.timeout(opts2.timeoutMs) } : {}
340388
341068
  });
340389
341069
  if (!res.ok) await fail(res);
340390
341070
  if (res.status === 204) return void 0;
@@ -340426,7 +341106,7 @@ function fieldsFromFlags(flags, ownFlags) {
340426
341106
  }
340427
341107
  return Object.keys(fields).length > 0 ? fields : void 0;
340428
341108
  }
340429
- function buildStageOp(cmd, flags, positional, readFile15 = (file) => fs48.readFileSync(file, "utf8")) {
341109
+ function buildStageOp(cmd, flags, positional, readFile16 = (file) => fs48.readFileSync(file, "utf8")) {
340430
341110
  switch (cmd) {
340431
341111
  case "link":
340432
341112
  return {
@@ -340448,7 +341128,7 @@ function buildStageOp(cmd, flags, positional, readFile15 = (file) => fs48.readFi
340448
341128
  ...flags.get("title") !== void 0 ? { title: flags.get("title") } : {},
340449
341129
  ...(flags.get("brief") ?? flags.get("description")) !== void 0 ? { description: flags.get("brief") ?? flags.get("description") } : {},
340450
341130
  ...flags.get("input") !== void 0 ? { inputs: flags.get("input").split(",").map((to) => ({ to: to.trim() })) } : {},
340451
- ...partsFile !== void 0 ? { parts: JSON.parse(readFile15(partsFile)) } : {},
341131
+ ...partsFile !== void 0 ? { parts: JSON.parse(readFile16(partsFile)) } : {},
340452
341132
  ...fields !== void 0 ? { fields } : {}
340453
341133
  };
340454
341134
  }
@@ -340727,7 +341407,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
340727
341407
  const store = createNodeTokenStore(path42.join(dir, "node-tokens.json"));
340728
341408
  const sub = positional[0];
340729
341409
  if (sub === "issue") {
340730
- const id = flags.get("id") ?? `node-${(0, import_node_crypto108.randomUUID)()}`;
341410
+ const id = flags.get("id") ?? `node-${(0, import_node_crypto110.randomUUID)()}`;
340731
341411
  const token3 = store.issue(id);
340732
341412
  println(token3);
340733
341413
  process.stderr.write(
@@ -340966,6 +341646,21 @@ async function runCli(argv, println = console.log, progressln = console.error) {
340966
341646
  if (!graph) return;
340967
341647
  for (const line2 of renderGraphLines(graph)) println(line2);
340968
341648
  };
341649
+ const printOverlap = async (action, text7, subjectId) => {
341650
+ if (!text7.trim()) return;
341651
+ try {
341652
+ const chatSessionId = process.env["OASIS_CHAT_SESSION_ID"];
341653
+ const r5 = await api.request("POST", "/api/overlap/candidates", {
341654
+ action,
341655
+ text: text7,
341656
+ ...subjectId ? { subjectId } : {},
341657
+ ...chatSessionId ? { chatSessionId } : {}
341658
+ }, { timeoutMs: OVERLAP_TIMEOUT_MS });
341659
+ if (!r5?.enabled) return;
341660
+ for (const line2 of formatOverlapLines(r5, r5.timeZone)) println(line2);
341661
+ } catch {
341662
+ }
341663
+ };
340969
341664
  if (process.env["OASIS_STAGE"] === "1" && STAGE_COMMANDS.has(command6)) {
340970
341665
  const op2 = buildStageOp(command6, flags, positional, readFileArg);
340971
341666
  const editWs = flags.get("workspace") ?? process.env["OASIS_WORKSPACE"];
@@ -341043,7 +341738,32 @@ async function runCli(argv, println = console.log, progressln = console.error) {
341043
341738
  const statusRef = flags.get("status");
341044
341739
  if (statusRef !== void 0) {
341045
341740
  if (statusRef === "true") throw new Error("--status \u8981\u8DDF\u4E00\u4E2A\u5F15\u7528\uFF1Alabel / \u4E13\u5BB6\u540D / delegationId \u524D\u7F00");
341046
- const target = await resolveRef2(statusRef);
341741
+ let target;
341742
+ try {
341743
+ target = await resolveRef2(statusRef);
341744
+ } catch (error3) {
341745
+ const ref2 = statusRef.trim();
341746
+ if (!DELEGATION_ID_RE.test(ref2)) throw error3;
341747
+ const summary = await api.request("GET", `/api/delegations/${encodeURIComponent(ref2)}/summary`);
341748
+ if (asJson2) {
341749
+ println(JSON.stringify(summary, null, 2));
341750
+ break;
341751
+ }
341752
+ println("\uFF08\u8FD9\u6761\u4E0D\u662F\u672C\u6BB5\u5BF9\u8BDD\u6D3E\u51FA\u7684\u59D4\u6D3E\u2014\u2014\u4EE5\u4E0B\u662F\u53EA\u8BFB\u6458\u8981\uFF0C\u4E0D\u542B\u5B50\u4F1A\u8BDD\u8FC7\u7A0B\uFF1B--follow-up \u53EA\u6709\u6D3E\u6D3B\u7684\u90A3\u6BB5\u5BF9\u8BDD\u80FD\u7528\u3002\uFF09");
341753
+ println(`${summary.label ?? "(\u65E0\u77ED\u540D)"} ${summary.expertName ?? summary.expertActorId} ${summary.state}${summary.failureKind ? `/${summary.failureKind}` : ""}`);
341754
+ println(`id=${summary.id} \u5B50\u4F1A\u8BDD=${summary.childSessionId} \u6D3E\u6D3B\u5BF9\u8BDD=${summary.parentSessionId} \u6D3E\u6D3B\u4EBA=${summary.delegatorName ?? summary.delegatorActorId ?? "\uFF08\u672A\u77E5\uFF09"}`);
341755
+ println(`\u6D3E\u51FA\uFF1A${summary.createdAt}${summary.settledAt ? ` \u4EA4\u56DE\uFF1A${summary.settledAt}` : ""}`);
341756
+ println(`\u4EFB\u52A1\u4E66${summary.taskTruncated ? "\uFF08\u53EA\u6709\u9996\u53E5\u6458\u8981\uFF09" : ""}\uFF1A`);
341757
+ println(summary.task || "\uFF08\u7A7A\uFF09");
341758
+ for (const round of summary.rounds) println(`
341759
+ \u7B2C ${round.round} \u8F6E\uFF08${round.at}\uFF09\uFF1A
341760
+ ${round.text}`);
341761
+ if (summary.artifacts.length > 0) {
341762
+ println("\n\u4EA7\u51FA\uFF1A");
341763
+ for (const name of summary.artifacts) println(` ${name}`);
341764
+ }
341765
+ break;
341766
+ }
341047
341767
  const detail = await api.request("GET", `/api/delegations/${encodeURIComponent(target.id)}`);
341048
341768
  if (asJson2) {
341049
341769
  println(JSON.stringify(detail, null, 2));
@@ -341075,17 +341795,17 @@ ${round.text}`);
341075
341795
  println(JSON.stringify({ delegationId: target.id, label: target.label, files: fileArgs, ...outcome }, null, 2));
341076
341796
  break;
341077
341797
  }
341078
- const who = `${target.expertName ?? target.expertActorId}\uFF08${target.label ?? target.id.slice(0, 8)}\uFF09`;
341798
+ const who2 = `${target.expertName ?? target.expertActorId}\uFF08${target.label ?? target.id.slice(0, 8)}\uFF09`;
341079
341799
  if (outcome?.outcome === "inserted") {
341080
- println(`\u5DF2\u63D2\u8FDB ${who} \u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E\u2014\u2014\u5B83\u628A\u5F53\u524D\u8FD9\u4E00\u6B65\u7B54\u5B8C\u5C31\u4F1A\u770B\u5230\u3002`);
341800
+ println(`\u5DF2\u63D2\u8FDB ${who2} \u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E\u2014\u2014\u5B83\u628A\u5F53\u524D\u8FD9\u4E00\u6B65\u7B54\u5B8C\u5C31\u4F1A\u770B\u5230\u3002`);
341081
341801
  } else if (outcome?.outcome === "started-round") {
341082
- println(`\u5DF2\u8F6C\u8FBE\u7ED9 ${who}\uFF1A\u5B83\u4E0A\u4E00\u8F6E\u5DF2\u7ECF\u7ED3\u675F\uFF0C\u8FD9\u53E5\u8BDD\u5F53\u573A\u8D77\u4E86\u65B0\u7684\u4E00\u8F6E\u3002`);
341802
+ println(`\u5DF2\u8F6C\u8FBE\u7ED9 ${who2}\uFF1A\u5B83\u4E0A\u4E00\u8F6E\u5DF2\u7ECF\u7ED3\u675F\uFF0C\u8FD9\u53E5\u8BDD\u5F53\u573A\u8D77\u4E86\u65B0\u7684\u4E00\u8F6E\u3002`);
341083
341803
  } else if (outcome?.outcome === "queued") {
341084
- println(`\u5DF2\u6536\u4E0B\uFF0C\u4F46${who}**\u73B0\u5728\u8FD8\u770B\u4E0D\u5230**\uFF1A${outcome.reason ?? "\u63D2\u4E0D\u8FDB\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E"}\u3002`);
341804
+ println(`\u5DF2\u6536\u4E0B\uFF0C\u4F46${who2}**\u73B0\u5728\u8FD8\u770B\u4E0D\u5230**\uFF1A${outcome.reason ?? "\u63D2\u4E0D\u8FDB\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E"}\u3002`);
341085
341805
  println(` \u8FD9\u53E5\u8BDD\u6392\u5728\u5F85\u8F6C\u8FBE\u961F\u5217\u91CC\uFF08\u8FD8\u6709 ${outcome.pendingInputs} \u53E5\u6CA1\u9001\u5230\uFF09\uFF0C\u672C\u8F6E\u8DD1\u5B8C\u4F1A\u4F5C\u4E3A\u4E0B\u4E00\u8F6E\u53D1\u51FA\u3002`);
341086
341806
  println(" \u5B83\u8FD9\u4E00\u8F6E\u53EF\u80FD\u8FD8\u5728\u6309\u65E7\u65B9\u5411\u505A\u2014\u2014\u8981\u4E0D\u8981\u5728\u8FD9\u6761\u5BF9\u8BDD\u91CC\u5148\u8DDF\u7528\u6237\u8BF4\u660E\uFF0C\u4F60\u81EA\u5DF1\u5224\u65AD\u3002");
341087
341807
  } else {
341088
- println(`\u5DF2\u8F6C\u8FBE\u7ED9 ${who}\u3002`);
341808
+ println(`\u5DF2\u8F6C\u8FBE\u7ED9 ${who2}\u3002`);
341089
341809
  }
341090
341810
  if (fileArgs.length) println(` \u4E00\u8D77\u5E26\u8FC7\u53BB\u7684\u6587\u4EF6\uFF1A${fileArgs.join("\u3001")}`);
341091
341811
  println("\u8FD9\u4E00\u8F6E\u5230\u6B64\u4E3A\u6B62\uFF1A\u7ED3\u679C\u4F1A\u81EA\u5DF1\u56DE\u5230\u8FD9\u6761\u5BF9\u8BDD\uFF0C\u4E0D\u8981\u5728\u8FD9\u91CC\u7B49\u3002");
@@ -341106,6 +341826,7 @@ ${round.text}`);
341106
341826
  println(` delegationId\uFF1A${started.delegationId}`);
341107
341827
  if (started.attachedFiles?.length) println(` \u5E26\u8FC7\u53BB\u7684\u6587\u4EF6\uFF1A${started.attachedFiles.join("\u3001")}`);
341108
341828
  println("\u7ED3\u679C\u5E72\u5B8C\u4E86\u4F1A\u81EA\u5DF1\u56DE\u5230\u8FD9\u6761\u5BF9\u8BDD\u3002\u8FD9\u4E00\u8F6E\u5148\u6536\u5C3E\u2014\u2014\u53EF\u4EE5\u987A\u624B\u8DDF\u7528\u6237\u8BF4\u4E00\u53E5\u4F60\u628A\u8FD9\u4EF6\u4E8B\u6D3E\u51FA\u53BB\u4E86\u3002");
341829
+ await printOverlap("delegate", task, started.delegationId);
341109
341830
  break;
341110
341831
  }
341111
341832
  case "kb": {
@@ -341420,6 +342141,8 @@ ${p4.ref} ${p4.name}`);
341420
342141
  }
341421
342142
  }
341422
342143
  printGraph(graph);
342144
+ await printOverlap("run-playbook", `${title}
342145
+ ${description}`, res.workspaceId);
341423
342146
  break;
341424
342147
  }
341425
342148
  /* ---------- 自动化(Automations,ADR 0156):瘦客户端映射 /api/automations ---------- */
@@ -341654,6 +342377,11 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
341654
342377
  printGraph(detail.graph);
341655
342378
  }
341656
342379
  }
342380
+ await printOverlap(
342381
+ "create-workorder",
342382
+ [title, flags.get("goal"), flags.get("brief")].filter(Boolean).join("\n"),
342383
+ data?.workspace ?? /^planned (.+?): created/.exec(res.message)?.[1] ?? flags.get("workspace")
342384
+ );
341657
342385
  break;
341658
342386
  }
341659
342387
  case "workorders": {
@@ -341879,7 +342607,7 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
341879
342607
  if (!name) throw new Error("\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
341880
342608
  const goal = flags.get("goal")?.trim();
341881
342609
  const slug5 = flags.get("slug");
341882
- const id = slug5 !== void 0 ? projectSlug(slug5) : projectIdFromUuid((0, import_node_crypto108.randomUUID)());
342610
+ const id = slug5 !== void 0 ? projectSlug(slug5) : projectIdFromUuid((0, import_node_crypto110.randomUUID)());
341883
342611
  const result = await api.request("POST", "/api/projects", {
341884
342612
  ...id ? { id } : {},
341885
342613
  name,
@@ -342782,10 +343510,12 @@ ${res.warning}`);
342782
343510
  println(`\u8349\u6848\uFF08\u8FD8\u6CA1\u53D1\u51FA\uFF09\uFF1A\u6D3E\u7ED9 ${nameIn(r5.names)(r5.todo.assigneeActorId)}\uFF1A${r5.todo.title}\uFF0C${due(r5.todo)}`);
342783
343511
  println(`id\uFF1A${r5.todo.id}`);
342784
343512
  println("\u5BF9\u8BDD\u91CC\u5DF2\u51FA\u8349\u6848\u5361\uFF1A\u8BF7\u7528\u6237\u6838\u5BF9\u540E\u70B9\u300C\u53D1\u51FA\u300D\u3002\u53D1\u51FA\u524D\u5BF9\u65B9\u770B\u4E0D\u5230\u3001\u4E5F\u6536\u4E0D\u5230\u901A\u77E5\uFF1B\u8981\u6539\u5C31 oasis todo edit \u8FD9\u6761\u8349\u6848\u3002");
343513
+ await printOverlap("todo-add", [title, note].filter(Boolean).join("\n"), r5.todo.id);
342785
343514
  break;
342786
343515
  }
342787
343516
  println(`\u8BB0\u4E0B\u4E86\uFF1A${r5.todo.title}\uFF0C${due(r5.todo)}`);
342788
343517
  println(`id\uFF1A${r5.todo.id}`);
343518
+ await printOverlap("todo-add", [title, note].filter(Boolean).join("\n"), r5.todo.id);
342789
343519
  break;
342790
343520
  }
342791
343521
  if (sub === "list") {
@@ -342843,6 +343573,7 @@ ${res.warning}`);
342843
343573
  println(`\u627F\u63A5\u4EBA\u9996\u6B21\u67E5\u770B\uFF1A${t.firstViewedAt ? fmtAt(t.firstViewedAt) : "\uFF08\u8FD8\u6CA1\u770B\u8FC7\uFF09"}`);
342844
343574
  }
342845
343575
  if (t.linkedWorkorderId) println(`\u5DE5\u5355\uFF1A${t.linkedWorkorderId}`);
343576
+ if (t.result) println(`\u7ED3\u679C\u5728\u54EA\uFF1A${t.result}`);
342846
343577
  println("\u5907\u6CE8\uFF1A");
342847
343578
  println(t.note ? t.note : "\uFF08\u65E0\uFF09");
342848
343579
  const FIELD = {
@@ -342855,16 +343586,17 @@ ${res.warning}`);
342855
343586
  dueDate: "\u622A\u6B62\u65E5",
342856
343587
  dueTime: "\u622A\u6B62\u65F6\u523B",
342857
343588
  linkedWorkorderId: "\u5DE5\u5355",
342858
- assignee: "\u627F\u63A5\u4EBA"
343589
+ assignee: "\u627F\u63A5\u4EBA",
343590
+ result: "\u7ED3\u679C\u5728\u54EA"
342859
343591
  };
342860
343592
  const STATUS = { draft: "\u8349\u6848", open: "\u672A\u5B8C\u6210", done: "\u5DF2\u5B8C\u6210", cancelled: "\u5DF2\u53D6\u6D88" };
342861
343593
  const val = (field, v2) => v2 === void 0 || v2 === "" ? "\uFF08\u7A7A\uFF09" : field === "status" ? STATUS[v2] ?? v2 : field === "assignee" ? nm(v2) : v2;
342862
343594
  const changes = [...one2.changes].sort((a5, b6) => b6.at.localeCompare(a5.at));
342863
343595
  println(`\u53D8\u66F4\u8BB0\u5F55\uFF08${changes.length} \u6761\uFF0C\u65B0\u7684\u5728\u524D\uFF09\uFF1A`);
342864
343596
  for (const c5 of changes) {
342865
- const who = c5.handActorId ? `${nm(c5.actorId)}\uFF08\u7ECF\u624B ${c5.handActorId}\uFF09` : nm(c5.actorId);
343597
+ const who2 = c5.handActorId ? `${nm(c5.actorId)}\uFF08\u7ECF\u624B ${c5.handActorId}\uFF09` : nm(c5.actorId);
342866
343598
  const what = c5.field === "created" ? `\u8BB0\u4E0B\uFF1A${c5.newValue ?? ""}` : c5.field === "sent" ? `\u53D1\u51FA\uFF1A\u6D3E\u7ED9 ${nm(c5.newValue ?? "")}` : `${FIELD[c5.field] ?? c5.field}\uFF1A${val(c5.field, c5.oldValue)} \u2192 ${val(c5.field, c5.newValue)}`;
342867
- println(`- ${fmtAt(c5.at)} ${who} ${what}${c5.reason ? ` \u539F\u56E0\uFF1A${c5.reason}` : ""}`);
343599
+ println(`- ${fmtAt(c5.at)} ${who2} ${what}${c5.reason ? ` \u539F\u56E0\uFF1A${c5.reason}` : ""}`);
342868
343600
  }
342869
343601
  break;
342870
343602
  }
@@ -342879,7 +343611,8 @@ ${res.warning}`);
342879
343611
  if (flags.has("start-time")) body2["startTime"] = flags.get("start-time") === "none" ? null : checkTime(flags.get("start-time"), "start-time");
342880
343612
  if (flags.has("workorder")) body2["linkedWorkorderId"] = flags.get("workorder") === "none" ? null : flags.get("workorder");
342881
343613
  if (flags.has("to")) body2["assignee"] = flags.get("to");
342882
- if (Object.keys(body2).length === 0) throw new Error("\u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\uFF1A\u7ED9 --title / --note / --start / --start-time / --due / --time / --workorder / --to \u91CC\u7684\u81F3\u5C11\u4E00\u4E2A");
343614
+ if (flags.has("result")) body2["result"] = flags.get("result") === "none" ? null : flags.get("result");
343615
+ if (Object.keys(body2).length === 0) throw new Error("\u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\uFF1A\u7ED9 --title / --note / --start / --start-time / --due / --time / --workorder / --to / --result \u91CC\u7684\u81F3\u5C11\u4E00\u4E2A");
342883
343616
  if (flags.get("reason")) body2["reason"] = flags.get("reason");
342884
343617
  const r5 = await call("PATCH", todoPath(id), body2);
342885
343618
  println(r5.todayLine);
@@ -342889,9 +343622,13 @@ ${res.warning}`);
342889
343622
  if (sub === "done" || sub === "cancel" || sub === "reopen") {
342890
343623
  const id = idOf();
342891
343624
  const reason = flags.get("reason");
342892
- const r5 = await call("POST", todoPath(id, `/${sub}`), reason ? { reason } : {});
343625
+ const result = flags.get("result");
343626
+ if (result !== void 0 && sub !== "done") throw new Error("--result \u53EA\u914D oasis todo done\uFF1B\u8981\u6539\u7ED3\u679C\u5728\u54EA\u7528 oasis todo edit <id> --result \u2026");
343627
+ if (result !== void 0 && !result.trim()) throw new Error("--result \u8981\u5199\u7ED3\u679C\u5728\u54EA\uFF08\u6587\u4EF6 / \u94FE\u63A5 / \u5DE5\u5355 id\uFF09\uFF1B\u7528\u6237\u8BF4\u4E0D\u7528\u8BB0\u5C31\u522B\u7ED9 --result");
343628
+ const r5 = await call("POST", todoPath(id, `/${sub}`), { ...reason ? { reason } : {}, ...result ? { result } : {} });
342893
343629
  println(r5.todayLine);
342894
343630
  println(`${sub === "done" ? "\u5DF2\u5B8C\u6210" : sub === "cancel" ? "\u5DF2\u53D6\u6D88" : "\u5DF2\u91CD\u65B0\u6253\u5F00"}\uFF1A${r5.todo.title}\uFF0C${due(r5.todo)}`);
343631
+ if (sub === "done" && r5.todo.result) println(`\u7ED3\u679C\u5728\u54EA\uFF1A${r5.todo.result}`);
342895
343632
  break;
342896
343633
  }
342897
343634
  throw new Error("\u7528\u6CD5: oasis todo <add|list|show|edit|done|cancel|reopen> \u2026\uFF08oasis todo --help \u770B\u8BE6\u60C5\uFF09");
@@ -344365,7 +345102,14 @@ function syncRuntimeAssets(candidateRoots, binDir) {
344365
345102
  }
344366
345103
  function runtimeAssetSourceRoots(input) {
344367
345104
  const roots = [];
344368
- if (input.executingBundle) roots.push(path47.dirname(input.executingBundle));
345105
+ if (input.executingBundle) {
345106
+ let bundle = input.executingBundle;
345107
+ try {
345108
+ bundle = fs53.realpathSync(bundle);
345109
+ } catch {
345110
+ }
345111
+ roots.push(path47.dirname(bundle));
345112
+ }
344369
345113
  try {
344370
345114
  roots.push(fs53.realpathSync(input.currentLink));
344371
345115
  } catch {
@@ -344440,13 +345184,13 @@ async function exchangeEnrollToken(o3) {
344440
345184
  }
344441
345185
 
344442
345186
  // src/install.ts
344443
- var import_node_crypto109 = require("node:crypto");
345187
+ var import_node_crypto111 = require("node:crypto");
344444
345188
  var fs54 = __toESM(require("node:fs"));
344445
345189
  var path48 = __toESM(require("node:path"));
344446
345190
  function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
344447
345191
  const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
344448
345192
  if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
344449
- const digest3 = (0, import_node_crypto109.createHash)("sha256").update(fs54.readFileSync(sourceFile)).digest("hex").slice(0, 8);
345193
+ const digest3 = (0, import_node_crypto111.createHash)("sha256").update(fs54.readFileSync(sourceFile)).digest("hex").slice(0, 8);
344450
345194
  return tag ? `${pkgVersion}${tag}.local.${digest3}` : `${pkgVersion}+local.${digest3}`;
344451
345195
  }
344452
345196
  function isFromNpmPrefix(sourceFile, npmPrefixDir) {
@@ -344569,7 +345313,7 @@ function shimScript() {
344569
345313
  }
344570
345314
 
344571
345315
  // src/index.ts
344572
- var PKG_VERSION = true ? "2.2.121" : "dev";
345316
+ var PKG_VERSION = true ? "2.2.123" : "dev";
344573
345317
  var LOCAL_BIN = localBin();
344574
345318
  var NPM_PREFIX = npmPrefix();
344575
345319
  var INSTANCE = DEFAULT_INSTANCE;
@@ -344877,7 +345621,7 @@ function newInstanceName() {
344877
345621
  const existing = new Set(listInstances());
344878
345622
  if (!existing.has(DEFAULT_INSTANCE)) return DEFAULT_INSTANCE;
344879
345623
  for (; ; ) {
344880
- const n3 = `inst-${(0, import_node_crypto110.randomBytes)(3).toString("hex")}`;
345624
+ const n3 = `inst-${(0, import_node_crypto112.randomBytes)(3).toString("hex")}`;
344881
345625
  if (!existing.has(n3)) return n3;
344882
345626
  }
344883
345627
  }