botmux 2.69.0 → 2.71.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/sandbox.d.ts +7 -0
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +85 -9
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/cli/antigravity.d.ts.map +1 -1
- package/dist/adapters/cli/antigravity.js +1 -0
- package/dist/adapters/cli/antigravity.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts +2 -0
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +3 -0
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/coco.d.ts.map +1 -1
- package/dist/adapters/cli/coco.js +1 -0
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app.js +1 -0
- package/dist/adapters/cli/codex-app.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +2 -0
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/gemini.d.ts.map +1 -1
- package/dist/adapters/cli/gemini.js +1 -0
- package/dist/adapters/cli/gemini.js.map +1 -1
- package/dist/adapters/cli/mtr.d.ts.map +1 -1
- package/dist/adapters/cli/mtr.js +1 -0
- package/dist/adapters/cli/mtr.js.map +1 -1
- package/dist/adapters/cli/oh-my-pi.d.ts.map +1 -1
- package/dist/adapters/cli/oh-my-pi.js +1 -0
- package/dist/adapters/cli/oh-my-pi.js.map +1 -1
- package/dist/adapters/cli/opencode.d.ts.map +1 -1
- package/dist/adapters/cli/opencode.js +1 -0
- package/dist/adapters/cli/opencode.js.map +1 -1
- package/dist/adapters/cli/pi.d.ts.map +1 -1
- package/dist/adapters/cli/pi.js +1 -0
- package/dist/adapters/cli/pi.js.map +1 -1
- package/dist/adapters/cli/seed.d.ts.map +1 -1
- package/dist/adapters/cli/seed.js +1 -0
- package/dist/adapters/cli/seed.js.map +1 -1
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +1 -0
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +14 -0
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/core/command-handler.d.ts +6 -4
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +59 -12
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +13 -1
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/types.d.ts +16 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +23 -2
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/core/zellij-adopt-discovery.d.ts.map +1 -1
- package/dist/core/zellij-adopt-discovery.js +5 -0
- package/dist/core/zellij-adopt-discovery.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +125 -1
- package/dist/daemon.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +4 -3
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +4 -3
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +6 -4
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +14 -7
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +35 -4
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.js +34 -4
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -41,7 +41,7 @@ import { createCliAdapterSync } from './adapters/cli/registry.js';
|
|
|
41
41
|
import { initWorkerPool, setActiveSessionsRegistry, forkWorker, killWorker, scheduleCardPatch, setCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, ensureCliEnv, writableTerminalLinkFor, } from './core/worker-pool.js';
|
|
42
42
|
import { ipcRoute, jsonRes, readJsonBody, setBotName, setLarkAppId, startIpcServer, setWorkflowRunner } from './core/dashboard-ipc-server.js';
|
|
43
43
|
import { saveFrozenCards } from './services/frozen-card-store.js';
|
|
44
|
-
import { DAEMON_COMMANDS, SESSIONLESS_DAEMON_COMMANDS, resolvePassthroughCommands, handleCommand, handleCardCommand, handleTermLinkCommand, parseSlashCommandInvocation, parseForceTopicInvocation } from './core/command-handler.js';
|
|
44
|
+
import { DAEMON_COMMANDS, SESSIONLESS_DAEMON_COMMANDS, resolvePassthroughCommands, resolveAdapterDefaultPassthroughCommands, handleCommand, handleCardCommand, handleTermLinkCommand, parseSlashCommandInvocation, parseForceTopicInvocation } from './core/command-handler.js';
|
|
45
45
|
import { findInheritablePeer } from './core/inherit-peer.js';
|
|
46
46
|
import { isCallbackUrl, handleCallbackUrl } from './utils/user-token.js';
|
|
47
47
|
import { consumeQuota, removeChatGrant, removeGlobalGrant } from './services/grant-store.js';
|
|
@@ -1693,6 +1693,90 @@ async function replyInvalidWorkingDirs(anchor, larkAppId, ds) {
|
|
|
1693
1693
|
logger.warn(`[${tag(ds)}] configured workingDir missing: ${invalid.join(', ')}`);
|
|
1694
1694
|
return true;
|
|
1695
1695
|
}
|
|
1696
|
+
function isInitialSessionPassthrough(larkAppId, cmd) {
|
|
1697
|
+
return resolveAdapterDefaultPassthroughCommands(larkAppId).includes(cmd);
|
|
1698
|
+
}
|
|
1699
|
+
async function startInitialPassthroughSession(args) {
|
|
1700
|
+
const { larkAppId, chatId, chatType, scope, anchor, messageId, replyRootId, parsed, commandContent, senderOpenId, ownerOpenId, ownerUnionId, creatorOpenId, } = args;
|
|
1701
|
+
if (!await enforceMessageQuotaForCliInput(larkAppId, chatId, senderOpenId, messageId, anchor)) {
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
const botCfg = getBot(larkAppId).config;
|
|
1705
|
+
refreshCliVersion(botCfg.cliId, botCfg.cliPathOverride);
|
|
1706
|
+
const rootIdForStore = scope === 'thread' ? anchor : messageId;
|
|
1707
|
+
const session = sessionStore.createSession(chatId, rootIdForStore, commandContent.substring(0, 50), chatType);
|
|
1708
|
+
const now = Date.now();
|
|
1709
|
+
session.larkAppId = larkAppId;
|
|
1710
|
+
session.ownerOpenId = ownerOpenId;
|
|
1711
|
+
session.creatorOpenId = creatorOpenId;
|
|
1712
|
+
session.ownerUnionId = ownerUnionId;
|
|
1713
|
+
session.lastCallerOpenId = senderOpenId;
|
|
1714
|
+
session.quoteTargetId = parsed.messageId;
|
|
1715
|
+
session.quoteTargetSenderOpenId = senderOpenId;
|
|
1716
|
+
session.quoteTargetSenderIsBot = parsed.senderType === 'app' || parsed.senderType === 'bot';
|
|
1717
|
+
session.lastMessageAt = new Date(now).toISOString();
|
|
1718
|
+
session.scope = scope;
|
|
1719
|
+
sessionStore.updateSession(session);
|
|
1720
|
+
messageQueue.ensureQueue(anchor);
|
|
1721
|
+
messageQueue.appendMessage(anchor, { ...parsed, content: commandContent });
|
|
1722
|
+
const { pinnedWorkingDir, oncallEntry, inheritedFrom } = await resolvePinnedWorkingDir({ scope, anchor, chatId, chatType, larkAppId });
|
|
1723
|
+
const ds = {
|
|
1724
|
+
session,
|
|
1725
|
+
worker: null,
|
|
1726
|
+
workerPort: null,
|
|
1727
|
+
workerToken: null,
|
|
1728
|
+
larkAppId,
|
|
1729
|
+
chatId,
|
|
1730
|
+
chatType,
|
|
1731
|
+
scope,
|
|
1732
|
+
spawnedAt: Date.parse(session.createdAt) || now,
|
|
1733
|
+
cliVersion: cliVersionCache.get(botCfg.cliId)?.version ?? 'unknown',
|
|
1734
|
+
lastMessageAt: now,
|
|
1735
|
+
hasHistory: false,
|
|
1736
|
+
pendingRepo: !pinnedWorkingDir,
|
|
1737
|
+
pendingPrompt: '',
|
|
1738
|
+
pendingRawInput: commandContent,
|
|
1739
|
+
ownerOpenId,
|
|
1740
|
+
currentTurnTitle: commandContent.substring(0, 50),
|
|
1741
|
+
workingDir: pinnedWorkingDir,
|
|
1742
|
+
};
|
|
1743
|
+
if (pinnedWorkingDir) {
|
|
1744
|
+
ds.session.workingDir = pinnedWorkingDir;
|
|
1745
|
+
sessionStore.updateSession(ds.session);
|
|
1746
|
+
}
|
|
1747
|
+
beginReplyTargetTurn(ds, replyRootId, messageId);
|
|
1748
|
+
sessionStore.updateSession(ds.session);
|
|
1749
|
+
activeSessions.set(sessionKey(anchor, larkAppId), ds);
|
|
1750
|
+
if (pinnedWorkingDir) {
|
|
1751
|
+
if (await replyInvalidWorkingDirs(anchor, larkAppId, ds))
|
|
1752
|
+
return;
|
|
1753
|
+
rememberLastCliInput(ds, commandContent, commandContent);
|
|
1754
|
+
forkWorker(ds, '', false);
|
|
1755
|
+
const reason = oncallEntry
|
|
1756
|
+
? `oncall-bound chat ${chatId}`
|
|
1757
|
+
: inheritedFrom
|
|
1758
|
+
? `inherited from sibling session ${inheritedFrom.sessionId.substring(0, 8)} (app=${inheritedFrom.larkAppId ?? 'unknown'})`
|
|
1759
|
+
: `bot defaultWorkingDir`;
|
|
1760
|
+
logger.info(`[${tag(ds)}] ${reason} → workingDir=${pinnedWorkingDir}, queued initial raw passthrough ${commandContent.substring(0, 40)}`);
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
if (await replyInvalidWorkingDirs(anchor, larkAppId, ds))
|
|
1764
|
+
return;
|
|
1765
|
+
const scanDirs = getProjectScanDirs(ds).filter(d => existsSync(d));
|
|
1766
|
+
const projects = scanDirs.length > 0 ? scanMultipleProjects(scanDirs) : [];
|
|
1767
|
+
if (projects.length > 0) {
|
|
1768
|
+
lastRepoScan.set(chatId, projects);
|
|
1769
|
+
const cardJson = buildRepoSelectCard(projects, getSessionWorkingDir(ds), anchor, localeForBot(larkAppId));
|
|
1770
|
+
ds.repoCardMessageId = await sessionReply(anchor, cardJson, 'interactive', larkAppId);
|
|
1771
|
+
announcePendingRepoSession(ds);
|
|
1772
|
+
logger.info(`[${tag(ds)}] Waiting for repo selection before initial raw passthrough (${projects.length} projects)`);
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
ds.pendingRepo = false;
|
|
1776
|
+
rememberLastCliInput(ds, commandContent, commandContent);
|
|
1777
|
+
forkWorker(ds, '', false);
|
|
1778
|
+
logger.info(`[${tag(ds)}] No projects to select, queued initial raw passthrough ${commandContent.substring(0, 40)}`);
|
|
1779
|
+
}
|
|
1696
1780
|
async function handleNewTopic(data, ctx) {
|
|
1697
1781
|
const { chatId, messageId, chatType, larkAppId, replyRootId } = ctx;
|
|
1698
1782
|
// scope/anchor are mutable here: `/t` / `/topic` may flip a 普通群 chat-scope
|
|
@@ -1783,6 +1867,26 @@ async function handleNewTopic(data, ctx) {
|
|
|
1783
1867
|
return;
|
|
1784
1868
|
}
|
|
1785
1869
|
if (resolvePassthroughCommands(larkAppId).has(cmd)) {
|
|
1870
|
+
if (isInitialSessionPassthrough(larkAppId, cmd)) {
|
|
1871
|
+
await startInitialPassthroughSession({
|
|
1872
|
+
larkAppId,
|
|
1873
|
+
chatId,
|
|
1874
|
+
chatType,
|
|
1875
|
+
scope,
|
|
1876
|
+
anchor,
|
|
1877
|
+
messageId,
|
|
1878
|
+
replyRootId,
|
|
1879
|
+
parsed,
|
|
1880
|
+
commandContent,
|
|
1881
|
+
senderOpenId,
|
|
1882
|
+
// New-topic senders are humans here (mirrors the normal new-topic
|
|
1883
|
+
// spawn path, which assigns ownership unconditionally too).
|
|
1884
|
+
ownerOpenId: senderOpenId,
|
|
1885
|
+
ownerUnionId: senderUnionId,
|
|
1886
|
+
creatorOpenId: senderOpenId,
|
|
1887
|
+
});
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1786
1890
|
await sessionReply(anchor, tr('daemon.cmd_requires_session', { cmd }, localeForBot(larkAppId)), 'text', larkAppId);
|
|
1787
1891
|
return;
|
|
1788
1892
|
}
|
|
@@ -2337,6 +2441,26 @@ async function handleThreadReply(data, ctx) {
|
|
|
2337
2441
|
return;
|
|
2338
2442
|
}
|
|
2339
2443
|
if (resolvePassthroughCommands(larkAppId).has(cmd)) {
|
|
2444
|
+
if (!existingDs && threadChatId && isInitialSessionPassthrough(larkAppId, cmd)) {
|
|
2445
|
+
await startInitialPassthroughSession({
|
|
2446
|
+
larkAppId,
|
|
2447
|
+
chatId: threadChatId,
|
|
2448
|
+
chatType: ctxChatType,
|
|
2449
|
+
scope,
|
|
2450
|
+
anchor,
|
|
2451
|
+
messageId: parsed.messageId,
|
|
2452
|
+
replyRootId,
|
|
2453
|
+
parsed,
|
|
2454
|
+
commandContent,
|
|
2455
|
+
senderOpenId: threadSenderOpenId,
|
|
2456
|
+
// Bot-started cold starts get no human owner (mirrors the auto-create
|
|
2457
|
+
// path) — see the ownership note on startInitialPassthroughSession.
|
|
2458
|
+
ownerOpenId: isForeignBot ? undefined : threadSenderOpenId,
|
|
2459
|
+
ownerUnionId: isForeignBot ? undefined : data?.sender?.sender_id?.union_id,
|
|
2460
|
+
creatorOpenId: threadSenderOpenId,
|
|
2461
|
+
});
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2340
2464
|
// 语义边界(刻意保留,非疏漏):passthrough(/model /clear /compact 等)按
|
|
2341
2465
|
// “发给 CLI 的对话输入”处理,因此不过下面 DAEMON_COMMANDS 的 oncall
|
|
2342
2466
|
// canOperate 闸 —— oncall 放行的就是对话输入,canOperate 只管 botmux
|