botmux 2.67.0 → 2.68.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.
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +7 -2
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +12 -5
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app.js +5 -17
- package/dist/adapters/cli/codex-app.js.map +1 -1
- package/dist/adapters/cli/mira.d.ts.map +1 -1
- package/dist/adapters/cli/mira.js +4 -17
- package/dist/adapters/cli/mira.js.map +1 -1
- package/dist/adapters/cli/pi.d.ts.map +1 -1
- package/dist/adapters/cli/pi.js +0 -1
- package/dist/adapters/cli/pi.js.map +1 -1
- package/dist/adapters/cli/runner-input.d.ts +66 -0
- package/dist/adapters/cli/runner-input.d.ts.map +1 -0
- package/dist/adapters/cli/runner-input.js +125 -0
- package/dist/adapters/cli/runner-input.js.map +1 -0
- package/dist/adapters/cli/types.d.ts +8 -4
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +79 -17
- package/dist/cli.js.map +1 -1
- package/dist/core/auto-start.d.ts +23 -0
- package/dist/core/auto-start.d.ts.map +1 -1
- package/dist/core/auto-start.js +30 -0
- package/dist/core/auto-start.js.map +1 -1
- package/dist/core/command-handler.d.ts +9 -9
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +23 -16
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/cost-calculator.d.ts +27 -0
- package/dist/core/cost-calculator.d.ts.map +1 -1
- package/dist/core/cost-calculator.js +483 -27
- package/dist/core/cost-calculator.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +3 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +11 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +22 -1
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +15 -6
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +4 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +16 -1
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard-web/app.js +120 -116
- package/dist/dashboard-web/style.css +4 -0
- package/dist/dashboard.js +41 -13
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.js +2 -2
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.js +2 -2
- package/dist/i18n/zh.js.map +1 -1
- package/dist/services/aiden-checkpoints.d.ts +5 -0
- package/dist/services/aiden-checkpoints.d.ts.map +1 -0
- package/dist/services/aiden-checkpoints.js +91 -0
- package/dist/services/aiden-checkpoints.js.map +1 -0
- package/dist/services/codex-transcript.d.ts +7 -0
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js +60 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/usage-ledger.d.ts +81 -0
- package/dist/services/usage-ledger.d.ts.map +1 -0
- package/dist/services/usage-ledger.js +353 -0
- package/dist/services/usage-ledger.js.map +1 -0
- package/package.json +1 -1
|
@@ -58,4 +58,27 @@ export declare function chatHasAllowedUser(memberOpenIds: Iterable<string>, allo
|
|
|
58
58
|
* produces a non-empty CLI turn (FR-11).
|
|
59
59
|
*/
|
|
60
60
|
export declare function resolveGroupJoinPrompt(configured: string | undefined): string;
|
|
61
|
+
/**
|
|
62
|
+
* 场景①: D7 gate with retry — wait for an allowedUser to appear in the chat.
|
|
63
|
+
*
|
|
64
|
+
* Alarm/oncall platforms that auto-create incident chats (e.g. ByteDance
|
|
65
|
+
* Nexus) add the bot FIRST and the human members moments later. A one-shot
|
|
66
|
+
* membership snapshot taken at bot.added time races against that and loses:
|
|
67
|
+
* the chat looks like it has no allowedUser and auto-start is silently
|
|
68
|
+
* skipped even though the owner lands in the chat a second later. Re-check
|
|
69
|
+
* membership a few times with backoff before giving up.
|
|
70
|
+
*
|
|
71
|
+
* Attempts = retryDelaysMs.length + 1 (default 4 attempts over ~25s). Errors
|
|
72
|
+
* from `listMembers` propagate to the caller on ANY attempt — same handling
|
|
73
|
+
* as the previous one-shot check (warn + scope hint). Empty allowedUsers
|
|
74
|
+
* short-circuits to false without calling `listMembers` (FR-2).
|
|
75
|
+
*/
|
|
76
|
+
export declare function waitForAllowedUserInChat(opts: {
|
|
77
|
+
listMembers: () => Promise<string[]>;
|
|
78
|
+
allowedUsers: Iterable<string>;
|
|
79
|
+
/** Waits BETWEEN attempts (ms). Default [3000, 7000, 15000]. */
|
|
80
|
+
retryDelaysMs?: number[];
|
|
81
|
+
sleep?: (ms: number) => Promise<void>;
|
|
82
|
+
onRetry?: (attempt: number, delayMs: number) => void;
|
|
83
|
+
}): Promise<boolean>;
|
|
61
84
|
//# sourceMappingURL=auto-start.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-start.d.ts","sourceRoot":"","sources":["../../src/core/auto-start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,oBAAoB,EAAE,OAAO,CAAC;IAC9B,+EAA+E;IAC/E,0BAA0B,EAAE,MAAM,CAAC;IACnC,2EAA2E;IAC3E,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAQV;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC/B,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,GACnC,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE7E"}
|
|
1
|
+
{"version":3,"file":"auto-start.d.ts","sourceRoot":"","sources":["../../src/core/auto-start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,oBAAoB,EAAE,OAAO,CAAC;IAC9B,+EAA+E;IAC/E,0BAA0B,EAAE,MAAM,CAAC;IACnC,2EAA2E;IAC3E,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAQV;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC/B,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,GACnC,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD,GAAG,OAAO,CAAC,OAAO,CAAC,CAWnB"}
|
package/dist/core/auto-start.js
CHANGED
|
@@ -59,4 +59,34 @@ export function chatHasAllowedUser(memberOpenIds, allowedUserOpenIds) {
|
|
|
59
59
|
export function resolveGroupJoinPrompt(configured) {
|
|
60
60
|
return (configured ?? '').trim();
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* 场景①: D7 gate with retry — wait for an allowedUser to appear in the chat.
|
|
64
|
+
*
|
|
65
|
+
* Alarm/oncall platforms that auto-create incident chats (e.g. ByteDance
|
|
66
|
+
* Nexus) add the bot FIRST and the human members moments later. A one-shot
|
|
67
|
+
* membership snapshot taken at bot.added time races against that and loses:
|
|
68
|
+
* the chat looks like it has no allowedUser and auto-start is silently
|
|
69
|
+
* skipped even though the owner lands in the chat a second later. Re-check
|
|
70
|
+
* membership a few times with backoff before giving up.
|
|
71
|
+
*
|
|
72
|
+
* Attempts = retryDelaysMs.length + 1 (default 4 attempts over ~25s). Errors
|
|
73
|
+
* from `listMembers` propagate to the caller on ANY attempt — same handling
|
|
74
|
+
* as the previous one-shot check (warn + scope hint). Empty allowedUsers
|
|
75
|
+
* short-circuits to false without calling `listMembers` (FR-2).
|
|
76
|
+
*/
|
|
77
|
+
export async function waitForAllowedUserInChat(opts) {
|
|
78
|
+
const allowed = [...opts.allowedUsers];
|
|
79
|
+
if (allowed.length === 0)
|
|
80
|
+
return false;
|
|
81
|
+
const delays = opts.retryDelaysMs ?? [3000, 7000, 15000];
|
|
82
|
+
const sleep = opts.sleep ?? ((ms) => new Promise(r => setTimeout(r, ms)));
|
|
83
|
+
for (let attempt = 0;; attempt++) {
|
|
84
|
+
if (chatHasAllowedUser(await opts.listMembers(), allowed))
|
|
85
|
+
return true;
|
|
86
|
+
if (attempt >= delays.length)
|
|
87
|
+
return false;
|
|
88
|
+
opts.onRetry?.(attempt + 1, delays[attempt]);
|
|
89
|
+
await sleep(delays[attempt]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
62
92
|
//# sourceMappingURL=auto-start.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-start.js","sourceRoot":"","sources":["../../src/core/auto-start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAOzC;IACC,OAAO,CACL,IAAI,CAAC,OAAO;QACZ,IAAI,CAAC,QAAQ,KAAK,OAAO;QACzB,IAAI,CAAC,KAAK,KAAK,QAAQ;QACvB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,SAAS;QAC9B,CAAC,IAAI,CAAC,WAAW,CAClB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,aAA+B,EAC/B,kBAAoC;IAEpC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAA8B;IACnE,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC"}
|
|
1
|
+
{"version":3,"file":"auto-start.js","sourceRoot":"","sources":["../../src/core/auto-start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAOzC;IACC,OAAO,CACL,IAAI,CAAC,OAAO;QACZ,IAAI,CAAC,QAAQ,KAAK,OAAO;QACzB,IAAI,CAAC,KAAK,KAAK,QAAQ;QACvB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,SAAS;QAC9B,CAAC,IAAI,CAAC,WAAW,CAClB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,aAA+B,EAC/B,kBAAoC;IAEpC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAA8B;IACnE,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,IAO9C;IACC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACxF,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;QAClC,IAAI,kBAAkB,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QACvE,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,GAAG,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7C,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC"}
|
|
@@ -89,7 +89,7 @@ export interface CommandHandlerDeps {
|
|
|
89
89
|
lastRepoScan: Map<string, import('../services/project-scanner.js').ProjectInfo[]>;
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
* Handle `/card` (
|
|
92
|
+
* Handle `/card` (operator-only). Resolves the active session itself, so off/on
|
|
93
93
|
* work WITHOUT one -- they only toggle the per-chat `noCardChats` config. A
|
|
94
94
|
* summon (show/bare) needs a live session.
|
|
95
95
|
*
|
|
@@ -103,15 +103,15 @@ export interface CommandHandlerDeps {
|
|
|
103
103
|
*/
|
|
104
104
|
export declare function handleCardCommand(rootId: string, larkAppId: string, chatId: string, senderOpenId: string | undefined, content: string, deps: CommandHandlerDeps): Promise<void>;
|
|
105
105
|
/**
|
|
106
|
-
* Handle `/term` (
|
|
107
|
-
* card button. Privately hands the
|
|
108
|
-
* an in-chat visible-to-you ephemeral card in plain groups, auto-falling back
|
|
109
|
-
* DM in topic / p2p chats. The link rides only that private channel — never the
|
|
110
|
-
* group. Gated identically to /card (`
|
|
111
|
-
*
|
|
112
|
-
*
|
|
106
|
+
* Handle `/term` (operator-only) — the slash-command twin of the "🔑 获取操作链接"
|
|
107
|
+
* card button. Privately hands the operator a writable (token-bearing) terminal
|
|
108
|
+
* card: an in-chat visible-to-you ephemeral card in plain groups, auto-falling back
|
|
109
|
+
* to a DM in topic / p2p chats. The link rides only that private channel — never the
|
|
110
|
+
* group. Gated identically to /card (`canOperate`), and strictly needs a live
|
|
111
|
+
* session whose terminal is up. Routed for both the new-topic path (daemon.ts) and
|
|
112
|
+
* the existing-session switch below.
|
|
113
113
|
*/
|
|
114
|
-
export declare function handleTermLinkCommand(rootId: string, larkAppId: string,
|
|
114
|
+
export declare function handleTermLinkCommand(rootId: string, larkAppId: string, chatId: string, senderOpenId: string | undefined, _content: string, deps: CommandHandlerDeps): Promise<void>;
|
|
115
115
|
export declare function handleCommand(cmd: string, rootId: string, message: LarkMessage, deps: CommandHandlerDeps, larkAppId?: string): Promise<void>;
|
|
116
116
|
export declare function startCodexAppThreadSession(thread: CodexAppThreadSummary, ds: DaemonSession, deps: CommandHandlerDeps, larkAppId?: string): Promise<void>;
|
|
117
117
|
export declare function startAdoptSession(target: AdoptableSession | ZellijAdoptableSession, ds: DaemonSession, deps: CommandHandlerDeps, larkAppId?: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../src/core/command-handler.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAoF,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACjJ,OAAO,EAA8D,KAAK,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACtI,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../src/core/command-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
|
6
6
|
import { join, resolve, basename } from 'node:path';
|
|
7
7
|
import { config } from '../config.js';
|
|
8
8
|
import { buildTerminalUrl } from './terminal-url.js';
|
|
9
|
-
import { getBot, getAllBots, getBotOpenId
|
|
9
|
+
import { getBot, getAllBots, getBotOpenId } from '../bot-registry.js';
|
|
10
10
|
import * as sessionStore from '../services/session-store.js';
|
|
11
11
|
import * as scheduleStore from '../services/schedule-store.js';
|
|
12
12
|
import * as scheduler from './scheduler.js';
|
|
@@ -31,6 +31,7 @@ import { CONFIG_FIELDS, findConfigField, settableFieldKeys, parseBooleanValue, a
|
|
|
31
31
|
import { resolveCliId, findInvalidAllowedUserEntries } from '../setup/bot-config-editor.js';
|
|
32
32
|
import { publishAttentionPatch, announcePendingRepoSession } from './session-activity.js';
|
|
33
33
|
import { setCardMode } from '../services/card-mode-store.js';
|
|
34
|
+
import { canOperate } from '../im/lark/event-dispatcher.js';
|
|
34
35
|
import { invalidWorkingDirs } from '../utils/working-dir.js';
|
|
35
36
|
import { writeRoleFile, deleteRoleFile, resolveRole, resolveTeamRoleFile, writeTeamRoleFile, deleteTeamRoleFile } from './role-resolver.js';
|
|
36
37
|
import { getBotCapability, setBotCapability, clearBotCapability } from '../services/bot-profile-store.js';
|
|
@@ -709,7 +710,7 @@ async function handleConfigCommand(message, rootId, larkAppId, deps) {
|
|
|
709
710
|
}
|
|
710
711
|
// ─── Main command handler ────────────────────────────────────────────────────
|
|
711
712
|
/**
|
|
712
|
-
* Handle `/card` (
|
|
713
|
+
* Handle `/card` (operator-only). Resolves the active session itself, so off/on
|
|
713
714
|
* work WITHOUT one -- they only toggle the per-chat `noCardChats` config. A
|
|
714
715
|
* summon (show/bare) needs a live session.
|
|
715
716
|
*
|
|
@@ -724,9 +725,12 @@ async function handleConfigCommand(message, rootId, larkAppId, deps) {
|
|
|
724
725
|
export async function handleCardCommand(rootId, larkAppId, chatId, senderOpenId, content, deps) {
|
|
725
726
|
const loc = localeForBot(larkAppId);
|
|
726
727
|
const reply = (c) => deps.sessionReply(rootId, c, undefined, larkAppId);
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
728
|
+
// /card is an operator command — gate on canOperate, the same model every other
|
|
729
|
+
// daemon command uses. Open mode (no owner/allowlist) → canOperate passes for
|
|
730
|
+
// everyone; configured → any allowedUser (owner or co-owner); talk-only grantees
|
|
731
|
+
// (chatGrant/globalGrant/oncall members) are never operators.
|
|
732
|
+
if (!canOperate(larkAppId, chatId, senderOpenId)) {
|
|
733
|
+
await reply(t('cmd.card.operator_only', undefined, loc));
|
|
730
734
|
return;
|
|
731
735
|
}
|
|
732
736
|
const ds = deps.activeSessions.get(sessionKey(rootId, larkAppId));
|
|
@@ -782,20 +786,23 @@ export async function handleCardCommand(rootId, larkAppId, chatId, senderOpenId,
|
|
|
782
786
|
await reply(t('cmd.card.usage', undefined, loc));
|
|
783
787
|
}
|
|
784
788
|
/**
|
|
785
|
-
* Handle `/term` (
|
|
786
|
-
* card button. Privately hands the
|
|
787
|
-
* an in-chat visible-to-you ephemeral card in plain groups, auto-falling back
|
|
788
|
-
* DM in topic / p2p chats. The link rides only that private channel — never the
|
|
789
|
-
* group. Gated identically to /card (`
|
|
790
|
-
*
|
|
791
|
-
*
|
|
789
|
+
* Handle `/term` (operator-only) — the slash-command twin of the "🔑 获取操作链接"
|
|
790
|
+
* card button. Privately hands the operator a writable (token-bearing) terminal
|
|
791
|
+
* card: an in-chat visible-to-you ephemeral card in plain groups, auto-falling back
|
|
792
|
+
* to a DM in topic / p2p chats. The link rides only that private channel — never the
|
|
793
|
+
* group. Gated identically to /card (`canOperate`), and strictly needs a live
|
|
794
|
+
* session whose terminal is up. Routed for both the new-topic path (daemon.ts) and
|
|
795
|
+
* the existing-session switch below.
|
|
792
796
|
*/
|
|
793
|
-
export async function handleTermLinkCommand(rootId, larkAppId,
|
|
797
|
+
export async function handleTermLinkCommand(rootId, larkAppId, chatId, senderOpenId, _content, deps) {
|
|
794
798
|
const loc = localeForBot(larkAppId);
|
|
795
799
|
const reply = (c) => deps.sessionReply(rootId, c, undefined, larkAppId);
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
800
|
+
// /term is an operator command that hands out a *writable* terminal link — gate
|
|
801
|
+
// on canOperate (same model as other daemon commands). senderOpenId must be
|
|
802
|
+
// present: open-mode canOperate passes even an undefined sender, but the writable
|
|
803
|
+
// card is delivered privately to that exact open_id.
|
|
804
|
+
if (!senderOpenId || !canOperate(larkAppId, chatId, senderOpenId)) {
|
|
805
|
+
await reply(t('cmd.term.operator_only', undefined, loc));
|
|
799
806
|
return;
|
|
800
807
|
}
|
|
801
808
|
const ds = deps.activeSessions.get(sessionKey(rootId, larkAppId));
|