botmux 2.97.0 → 2.98.0

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 (35) hide show
  1. package/dist/core/dashboard-url.d.ts +22 -0
  2. package/dist/core/dashboard-url.d.ts.map +1 -0
  3. package/dist/core/dashboard-url.js +24 -0
  4. package/dist/core/dashboard-url.js.map +1 -0
  5. package/dist/daemon.d.ts.map +1 -1
  6. package/dist/daemon.js +13 -9
  7. package/dist/daemon.js.map +1 -1
  8. package/dist/dashboard/federation-spoke-api.d.ts.map +1 -1
  9. package/dist/dashboard/federation-spoke-api.js +10 -3
  10. package/dist/dashboard/federation-spoke-api.js.map +1 -1
  11. package/dist/dashboard.js +11 -3
  12. package/dist/dashboard.js.map +1 -1
  13. package/dist/global-config.d.ts +6 -0
  14. package/dist/global-config.d.ts.map +1 -1
  15. package/dist/global-config.js +8 -0
  16. package/dist/global-config.js.map +1 -1
  17. package/dist/im/lark/event-dispatcher.d.ts +18 -1
  18. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  19. package/dist/im/lark/event-dispatcher.js +47 -3
  20. package/dist/im/lark/event-dispatcher.js.map +1 -1
  21. package/dist/platform/bind.d.ts.map +1 -1
  22. package/dist/platform/bind.js +22 -1
  23. package/dist/platform/bind.js.map +1 -1
  24. package/dist/platform/tunnel-client.d.ts.map +1 -1
  25. package/dist/platform/tunnel-client.js +75 -29
  26. package/dist/platform/tunnel-client.js.map +1 -1
  27. package/dist/services/team-bots-store.d.ts +34 -0
  28. package/dist/services/team-bots-store.d.ts.map +1 -0
  29. package/dist/services/team-bots-store.js +111 -0
  30. package/dist/services/team-bots-store.js.map +1 -0
  31. package/dist/services/team-groups-store.d.ts +8 -0
  32. package/dist/services/team-groups-store.d.ts.map +1 -1
  33. package/dist/services/team-groups-store.js +12 -0
  34. package/dist/services/team-groups-store.js.map +1 -1
  35. package/package.json +1 -1
@@ -8,7 +8,16 @@ import { setPlatformTeams } from './binding.js';
8
8
  const HEARTBEAT_MS = 30_000;
9
9
  const BACKOFF_MIN_MS = 1_000;
10
10
  const BACKOFF_MAX_MS = 30_000;
11
- const DATA_DIAL_TIMEOUT_MS = 10_000;
11
+ // 数据流拨号:单次超时 + 有界重试。某些部署到平台 LB 某几个 VIP 的链路对 TLS/大包 ~50% 丢,
12
+ // 单拨一次就 502/掉 asset;像浏览器/CLI 那样「重试 + 复用」即可大幅救回。重试是「有界 + 限速」的:
13
+ // - 单次拨号超时缩到 3.5s(原 10s 太长,留不出重试窗口;健康链路拨号 <1s,不受影响)
14
+ // - 总拨号次数封顶 DATA_DIAL_MAX_ATTEMPTS(含首拨),绝不无限重试
15
+ // - 两次拨号间至少隔 DATA_DIAL_RETRY_BACKOFF_MS,控制 QPS,不猛拨
16
+ // - 总时长不超过 DATA_DIAL_OVERALL_DEADLINE_MS(平台 pending 流 10s 后作废,超了再拨也是白拨)
17
+ const DATA_DIAL_TIMEOUT_MS = 3_500;
18
+ const DATA_DIAL_MAX_ATTEMPTS = 3;
19
+ const DATA_DIAL_RETRY_BACKOFF_MS = 300;
20
+ const DATA_DIAL_OVERALL_DEADLINE_MS = 9_000;
12
21
  export function startPlatformTunnelClient(opts) {
13
22
  let stopped = false;
14
23
  let ws = null;
@@ -129,40 +138,77 @@ export function startPlatformTunnelClient(opts) {
129
138
  }
130
139
  function openDataStream(streamId) {
131
140
  const url = `${base}/tunnel/data?token=${tokenQ}&stream=${encodeURIComponent(streamId)}`;
132
- // 同上:数据流必须关 permessage-deflate,否则大文件(CSS/JS)帧经网关压缩协商错位 → RSV1 报错断流。
133
- const data = new WebSocket(url, { perMessageDeflate: false });
134
- const dialTimer = setTimeout(() => {
135
- try {
136
- data.terminate();
137
- }
138
- catch {
139
- /* ignore */
140
- }
141
- }, DATA_DIAL_TIMEOUT_MS);
142
- data.on('open', () => {
143
- clearTimeout(dialTimer);
144
- const dup = createWebSocketStream(data);
145
- const tcp = net.connect(opts.getDashboardPort(), '127.0.0.1');
146
- const kill = () => {
141
+ const startedAt = Date.now();
142
+ let attempt = 0;
143
+ const dial = () => {
144
+ attempt++;
145
+ // 同上:数据流必须关 permessage-deflate,否则大文件(CSS/JS)帧经网关压缩协商错位 → RSV1 报错断流。
146
+ const data = new WebSocket(url, { perMessageDeflate: false });
147
+ let settled = false; // 本次拨号是否已定局(成功桥接 / 失败转交重试),防 timer 与 error 重复触发
148
+ // 拨号失败(超时或 error):在预算内换一条新连接重试同一个 streamId(平台 pending 仍在);
149
+ // 超出次数/时间预算就放弃。绝不无限重试,两次之间留 backoff 限速。
150
+ const retryOrGiveUp = (reason) => {
151
+ const canRetry = attempt < DATA_DIAL_MAX_ATTEMPTS &&
152
+ Date.now() - startedAt < DATA_DIAL_OVERALL_DEADLINE_MS;
153
+ if (canRetry) {
154
+ opts.log('数据连接拨号失败,重试', { attempt, reason });
155
+ setTimeout(dial, DATA_DIAL_RETRY_BACKOFF_MS);
156
+ }
157
+ else {
158
+ opts.log('数据连接失败', { attempts: attempt, err: reason });
159
+ }
160
+ };
161
+ const dialTimer = setTimeout(() => {
162
+ if (settled)
163
+ return;
164
+ settled = true;
147
165
  try {
148
- dup.destroy();
166
+ data.terminate();
149
167
  }
150
168
  catch { /* ignore */ }
169
+ retryOrGiveUp(`dial timeout (${DATA_DIAL_TIMEOUT_MS}ms)`);
170
+ }, DATA_DIAL_TIMEOUT_MS);
171
+ data.on('open', () => {
172
+ if (settled) {
173
+ try {
174
+ data.terminate();
175
+ }
176
+ catch { /* ignore */ }
177
+ return;
178
+ }
179
+ settled = true;
180
+ clearTimeout(dialTimer);
181
+ const dup = createWebSocketStream(data);
182
+ const tcp = net.connect(opts.getDashboardPort(), '127.0.0.1');
183
+ const kill = () => {
184
+ try {
185
+ dup.destroy();
186
+ }
187
+ catch { /* ignore */ }
188
+ try {
189
+ tcp.destroy();
190
+ }
191
+ catch { /* ignore */ }
192
+ };
193
+ dup.on('error', kill);
194
+ tcp.on('error', kill);
195
+ tcp.on('close', kill);
196
+ dup.pipe(tcp);
197
+ tcp.pipe(dup);
198
+ });
199
+ data.on('error', (e) => {
200
+ if (settled)
201
+ return;
202
+ settled = true;
203
+ clearTimeout(dialTimer);
151
204
  try {
152
- tcp.destroy();
205
+ data.terminate();
153
206
  }
154
207
  catch { /* ignore */ }
155
- };
156
- dup.on('error', kill);
157
- tcp.on('error', kill);
158
- tcp.on('close', kill);
159
- dup.pipe(tcp);
160
- tcp.pipe(dup);
161
- });
162
- data.on('error', (e) => {
163
- clearTimeout(dialTimer);
164
- opts.log('数据连接失败', { err: String(e) });
165
- });
208
+ retryOrGiveUp(String(e));
209
+ });
210
+ };
211
+ dial();
166
212
  }
167
213
  connect();
168
214
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"tunnel-client.js","sourceRoot":"","sources":["../../src/platform/tunnel-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tunnel-client.js","sourceRoot":"","sources":["../../src/platform/tunnel-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /** Learned-teammate entries older than this (by lastSeenAt) are ignored by
2
+ * isTeamBot / listTeamBots — the bot hasn't shown up in a team context for a
3
+ * month, so we stop vouching for it until it's seen again. */
4
+ export declare const DEFAULT_EXPIRY_MS: number;
5
+ export interface TeamBot {
6
+ unionId: string;
7
+ name: string;
8
+ firstSeenAt: number;
9
+ lastSeenAt: number;
10
+ }
11
+ /**
12
+ * Upsert a learned teammate bot by union_id. Existing entry keeps firstSeenAt
13
+ * and bumps lastSeenAt (+ refreshes name); new entry stamps both.
14
+ *
15
+ * No-op when unionId is empty — many inbound bot events DO carry
16
+ * `sender.sender_id.union_id`, but the ones that don't simply can't be learned
17
+ * (and fall back to the existing /grant path), never polluting the store with a
18
+ * keyless entry. name may be empty (we still record the trusted union_id).
19
+ *
20
+ * Returns true iff the store changed (new entry or refreshed timestamp/name),
21
+ * so callers can skip a redundant log.
22
+ */
23
+ export declare function recordTeamBot(dataDir: string, bot: {
24
+ unionId: string | undefined;
25
+ name?: string;
26
+ }, now?: number): boolean;
27
+ /** Is `unionId` a known (non-expired) teammate bot? The auth gate's predicate.
28
+ * Empty/unknown/expired → false (caller falls back to /grant). */
29
+ export declare function isTeamBot(dataDir: string, unionId: string | undefined, maxAgeMs?: number, now?: number): boolean;
30
+ /** All non-expired learned teammate bots (for discovery / debugging). Unordered. */
31
+ export declare function listTeamBots(dataDir: string, maxAgeMs?: number, now?: number): TeamBot[];
32
+ /** Forget a learned teammate (explicit revoke). Returns true if removed. */
33
+ export declare function removeTeamBot(dataDir: string, unionId: string | undefined): boolean;
34
+ //# sourceMappingURL=team-bots-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-bots-store.d.ts","sourceRoot":"","sources":["../../src/services/team-bots-store.ts"],"names":[],"mappings":"AAiCA;;+DAE+D;AAC/D,eAAO,MAAM,iBAAiB,QAA2B,CAAC;AAE1D,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACnD,GAAG,GAAE,MAAmB,GACvB,OAAO,CAWT;AAED;mEACmE;AACnE,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,GAAE,MAA0B,EACpC,GAAG,GAAE,MAAmB,GACvB,OAAO,CAMT;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAA0B,EACpC,GAAG,GAAE,MAAmB,GACvB,OAAO,EAAE,CAQX;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAQnF"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Team-bot identity store: the tenant-stable `union_id` set of bots this
3
+ * deployment has learned are TEAMMATES, so the auth gate can let them
4
+ * collaborate without `/grant` (and without `/introduce` for discovery).
5
+ *
6
+ * Why union_id is the key (not name, not open_id):
7
+ * - **name is spoofable** — anyone in the tenant can run a bot called "Claude".
8
+ * Trust must never hinge on a self-reported display name.
9
+ * - **open_id is per-app scoped** — bot B's open_id as seen by app A ≠ as seen
10
+ * by app B, so it can't be a shared trust key across deployments.
11
+ * - **union_id is tenant-stable and cross-app consistent** — the same value in
12
+ * every app's view of the same bot, and Feishu vouches for it (it arrives on
13
+ * inbound events as `sender.sender_id.union_id`). It is the only sound key.
14
+ *
15
+ * Where entries come from (the trust ROOT — see recordTeamBot callers):
16
+ * - A bot observed talking inside a TEAM-ASSEMBLED group (a 拉群 group recorded
17
+ * in [[team-groups-store]]). Such groups are built by the team itself, adding
18
+ * bots by `larkAppId` from the federated roster — membership is team-controlled,
19
+ * so a bot speaking there is a vouched teammate. We capture its union_id here,
20
+ * then honour that union_id as a teammate in ANY group (incl. manually-created
21
+ * ones), without re-deriving trust from a spoofable name.
22
+ *
23
+ * Revocation / self-healing: entries carry lastSeenAt and expire after
24
+ * DEFAULT_EXPIRY_MS if the bot stops appearing in team contexts — so a bot that
25
+ * leaves the team ages out of the trusted set on its own.
26
+ *
27
+ * Storage: `{dataDir}/team-bots.json`, deployment-wide (not per-chat: trust in a
28
+ * teammate is global once established). Atomic writes via the shared helper.
29
+ */
30
+ import { readFileSync, existsSync } from 'node:fs';
31
+ import { join } from 'node:path';
32
+ import { atomicWriteFileSync } from '../utils/atomic-write.js';
33
+ /** Learned-teammate entries older than this (by lastSeenAt) are ignored by
34
+ * isTeamBot / listTeamBots — the bot hasn't shown up in a team context for a
35
+ * month, so we stop vouching for it until it's seen again. */
36
+ export const DEFAULT_EXPIRY_MS = 30 * 24 * 60 * 60 * 1000;
37
+ function filePath(dataDir) {
38
+ return join(dataDir, 'team-bots.json');
39
+ }
40
+ function readFile(dataDir) {
41
+ const fp = filePath(dataDir);
42
+ if (!existsSync(fp))
43
+ return {};
44
+ try {
45
+ const parsed = JSON.parse(readFileSync(fp, 'utf-8'));
46
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
47
+ return parsed;
48
+ }
49
+ catch { /* corrupt — fall through */ }
50
+ return {};
51
+ }
52
+ /**
53
+ * Upsert a learned teammate bot by union_id. Existing entry keeps firstSeenAt
54
+ * and bumps lastSeenAt (+ refreshes name); new entry stamps both.
55
+ *
56
+ * No-op when unionId is empty — many inbound bot events DO carry
57
+ * `sender.sender_id.union_id`, but the ones that don't simply can't be learned
58
+ * (and fall back to the existing /grant path), never polluting the store with a
59
+ * keyless entry. name may be empty (we still record the trusted union_id).
60
+ *
61
+ * Returns true iff the store changed (new entry or refreshed timestamp/name),
62
+ * so callers can skip a redundant log.
63
+ */
64
+ export function recordTeamBot(dataDir, bot, now = Date.now()) {
65
+ const unionId = (bot.unionId ?? '').trim();
66
+ if (!unionId)
67
+ return false;
68
+ const name = (bot.name ?? '').trim();
69
+ const data = readFile(dataDir);
70
+ const prior = data[unionId];
71
+ data[unionId] = prior
72
+ ? { ...prior, name: name || prior.name, lastSeenAt: now }
73
+ : { name, firstSeenAt: now, lastSeenAt: now };
74
+ atomicWriteFileSync(filePath(dataDir), JSON.stringify(data, null, 2) + '\n');
75
+ return true;
76
+ }
77
+ /** Is `unionId` a known (non-expired) teammate bot? The auth gate's predicate.
78
+ * Empty/unknown/expired → false (caller falls back to /grant). */
79
+ export function isTeamBot(dataDir, unionId, maxAgeMs = DEFAULT_EXPIRY_MS, now = Date.now()) {
80
+ const id = (unionId ?? '').trim();
81
+ if (!id)
82
+ return false;
83
+ const entry = readFile(dataDir)[id];
84
+ if (!entry)
85
+ return false;
86
+ return now - entry.lastSeenAt <= maxAgeMs;
87
+ }
88
+ /** All non-expired learned teammate bots (for discovery / debugging). Unordered. */
89
+ export function listTeamBots(dataDir, maxAgeMs = DEFAULT_EXPIRY_MS, now = Date.now()) {
90
+ const data = readFile(dataDir);
91
+ const out = [];
92
+ for (const [unionId, entry] of Object.entries(data)) {
93
+ if (now - entry.lastSeenAt > maxAgeMs)
94
+ continue;
95
+ out.push({ unionId, name: entry.name, firstSeenAt: entry.firstSeenAt, lastSeenAt: entry.lastSeenAt });
96
+ }
97
+ return out;
98
+ }
99
+ /** Forget a learned teammate (explicit revoke). Returns true if removed. */
100
+ export function removeTeamBot(dataDir, unionId) {
101
+ const id = (unionId ?? '').trim();
102
+ if (!id)
103
+ return false;
104
+ const data = readFile(dataDir);
105
+ if (!(id in data))
106
+ return false;
107
+ delete data[id];
108
+ atomicWriteFileSync(filePath(dataDir), JSON.stringify(data, null, 2) + '\n');
109
+ return true;
110
+ }
111
+ //# sourceMappingURL=team-bots-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-bots-store.js","sourceRoot":"","sources":["../../src/services/team-bots-store.ts"],"names":[],"mappings":"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"}
@@ -5,4 +5,12 @@ export interface TeamGroupBinding {
5
5
  }
6
6
  export declare function listTeamGroups(dataDir: string, teamId?: string): TeamGroupBinding[];
7
7
  export declare function recordTeamGroup(dataDir: string, teamId: string, chatId: string, now?: number): void;
8
+ /** Is `chatId` a team-assembled (拉群) group of ANY team? This is the TRUST ROOT
9
+ * for team-bot collaboration: such a group is built by the team (bots added by
10
+ * larkAppId from the federated roster), so a bot speaking there is a vouched
11
+ * teammate (see [[team-bots-store]]). Recorded on the orchestrating deployment
12
+ * by recordTeamGroup, and mirrored onto member deployments when the hub returns
13
+ * groupChatIds on federation sync — so every member's auth gate sees the same
14
+ * trust boundary. */
15
+ export declare function isTeamGroupChat(dataDir: string, chatId: string | undefined): boolean;
8
16
  //# sourceMappingURL=team-groups-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"team-groups-store.d.ts","sourceRoot":"","sources":["../../src/services/team-groups-store.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAAE,CASnF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAM/G"}
1
+ {"version":3,"file":"team-groups-store.d.ts","sourceRoot":"","sources":["../../src/services/team-groups-store.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAAE,CASnF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAM/G;AAED;;;;;;sBAMsB;AACtB,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGpF"}
@@ -28,4 +28,16 @@ export function recordTeamGroup(dataDir, teamId, chatId, now = Date.now()) {
28
28
  all.push({ teamId, chatId, createdAt: now });
29
29
  atomicWriteFileSync(filePath(dataDir), JSON.stringify(all, null, 2) + '\n');
30
30
  }
31
+ /** Is `chatId` a team-assembled (拉群) group of ANY team? This is the TRUST ROOT
32
+ * for team-bot collaboration: such a group is built by the team (bots added by
33
+ * larkAppId from the federated roster), so a bot speaking there is a vouched
34
+ * teammate (see [[team-bots-store]]). Recorded on the orchestrating deployment
35
+ * by recordTeamGroup, and mirrored onto member deployments when the hub returns
36
+ * groupChatIds on federation sync — so every member's auth gate sees the same
37
+ * trust boundary. */
38
+ export function isTeamGroupChat(dataDir, chatId) {
39
+ if (!chatId)
40
+ return false;
41
+ return listTeamGroups(dataDir).some(b => b.chatId === chatId);
42
+ }
31
43
  //# sourceMappingURL=team-groups-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"team-groups-store.js","sourceRoot":"","sources":["../../src/services/team-groups-store.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,gDAAgD;AAChD,+BAA+B;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAQ/D,SAAS,QAAQ,CAAC,OAAe;IAC/B,OAAO,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAAe;IAC7D,IAAI,GAAG,GAAuB,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IACnH,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;IACrB,CAAC;IACD,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,MAAc,EAAE,MAAc,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IACvG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM;QAAE,OAAO;IAC/B,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAAE,OAAO;IACtE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7C,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"team-groups-store.js","sourceRoot":"","sources":["../../src/services/team-groups-store.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,gDAAgD;AAChD,+BAA+B;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAQ/D,SAAS,QAAQ,CAAC,OAAe;IAC/B,OAAO,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAAe;IAC7D,IAAI,GAAG,GAAuB,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IACnH,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;IACrB,CAAC;IACD,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,MAAc,EAAE,MAAc,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IACvG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM;QAAE,OAAO;IAC/B,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAAE,OAAO;IACtE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7C,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;sBAMsB;AACtB,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,MAA0B;IACzE,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAChE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botmux",
3
- "version": "2.97.0",
3
+ "version": "2.98.0",
4
4
  "description": "Bridge between IM platforms and AI coding CLIs — one topic, one CLI session with live streaming",
5
5
  "type": "module",
6
6
  "main": "dist/index-daemon.js",