@barryfan2045/dsh-matrix 0.1.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/LICENSE +21 -0
- package/README.md +286 -0
- package/THIRD_PARTY_NOTICES.md +53 -0
- package/assets/avatars/instance-01.png +0 -0
- package/assets/avatars/instance-02.png +0 -0
- package/assets/avatars/instance-03.png +0 -0
- package/assets/avatars/instance-04.png +0 -0
- package/assets/avatars/instance-05.png +0 -0
- package/assets/avatars/instance-06.png +0 -0
- package/assets/avatars/instance-07.png +0 -0
- package/assets/avatars/instance-08.png +0 -0
- package/assets/avatars/instance-09.png +0 -0
- package/assets/avatars/instance-10.png +0 -0
- package/assets/avatars/instance-11.png +0 -0
- package/assets/avatars/instance-12.png +0 -0
- package/assets/avatars/management.png +0 -0
- package/cordis.patch.yml +13 -0
- package/dist/auth/admin-commands.d.ts +47 -0
- package/dist/auth/admin-commands.d.ts.map +1 -0
- package/dist/auth/admin-commands.js +112 -0
- package/dist/auth/admin-commands.js.map +1 -0
- package/dist/auth/challenge.d.ts +93 -0
- package/dist/auth/challenge.d.ts.map +1 -0
- package/dist/auth/challenge.js +104 -0
- package/dist/auth/challenge.js.map +1 -0
- package/dist/auth/store.d.ts +55 -0
- package/dist/auth/store.d.ts.map +1 -0
- package/dist/auth/store.js +124 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/bridge/agent-commands.d.ts +39 -0
- package/dist/bridge/agent-commands.d.ts.map +1 -0
- package/dist/bridge/agent-commands.js +243 -0
- package/dist/bridge/agent-commands.js.map +1 -0
- package/dist/bridge/attachments-ledger.d.ts +54 -0
- package/dist/bridge/attachments-ledger.d.ts.map +1 -0
- package/dist/bridge/attachments-ledger.js +68 -0
- package/dist/bridge/attachments-ledger.js.map +1 -0
- package/dist/bridge/commands.d.ts +28 -0
- package/dist/bridge/commands.d.ts.map +1 -0
- package/dist/bridge/commands.js +18 -0
- package/dist/bridge/commands.js.map +1 -0
- package/dist/bridge/crypto-health.d.ts +37 -0
- package/dist/bridge/crypto-health.d.ts.map +1 -0
- package/dist/bridge/crypto-health.js +38 -0
- package/dist/bridge/crypto-health.js.map +1 -0
- package/dist/bridge/group-gate.d.ts +38 -0
- package/dist/bridge/group-gate.d.ts.map +1 -0
- package/dist/bridge/group-gate.js +49 -0
- package/dist/bridge/group-gate.js.map +1 -0
- package/dist/bridge/instance-lock.d.ts +10 -0
- package/dist/bridge/instance-lock.d.ts.map +1 -0
- package/dist/bridge/instance-lock.js +82 -0
- package/dist/bridge/instance-lock.js.map +1 -0
- package/dist/bridge/interactions.d.ts +62 -0
- package/dist/bridge/interactions.d.ts.map +1 -0
- package/dist/bridge/interactions.js +237 -0
- package/dist/bridge/interactions.js.map +1 -0
- package/dist/bridge/management-room.d.ts +13 -0
- package/dist/bridge/management-room.d.ts.map +1 -0
- package/dist/bridge/management-room.js +27 -0
- package/dist/bridge/management-room.js.map +1 -0
- package/dist/bridge/multi-project.d.ts +34 -0
- package/dist/bridge/multi-project.d.ts.map +1 -0
- package/dist/bridge/multi-project.js +44 -0
- package/dist/bridge/multi-project.js.map +1 -0
- package/dist/bridge/pipeline.d.ts +151 -0
- package/dist/bridge/pipeline.d.ts.map +1 -0
- package/dist/bridge/pipeline.js +502 -0
- package/dist/bridge/pipeline.js.map +1 -0
- package/dist/bridge/pmctl.d.ts +50 -0
- package/dist/bridge/pmctl.d.ts.map +1 -0
- package/dist/bridge/pmctl.js +272 -0
- package/dist/bridge/pmctl.js.map +1 -0
- package/dist/bridge/power-levels.d.ts +57 -0
- package/dist/bridge/power-levels.d.ts.map +1 -0
- package/dist/bridge/power-levels.js +92 -0
- package/dist/bridge/power-levels.js.map +1 -0
- package/dist/bridge/power-sync.d.ts +64 -0
- package/dist/bridge/power-sync.d.ts.map +1 -0
- package/dist/bridge/power-sync.js +121 -0
- package/dist/bridge/power-sync.js.map +1 -0
- package/dist/bridge/projects.d.ts +97 -0
- package/dist/bridge/projects.d.ts.map +1 -0
- package/dist/bridge/projects.js +288 -0
- package/dist/bridge/projects.js.map +1 -0
- package/dist/bridge/quote-cache.d.ts +38 -0
- package/dist/bridge/quote-cache.d.ts.map +1 -0
- package/dist/bridge/quote-cache.js +56 -0
- package/dist/bridge/quote-cache.js.map +1 -0
- package/dist/bridge/reply.d.ts +31 -0
- package/dist/bridge/reply.d.ts.map +1 -0
- package/dist/bridge/reply.js +122 -0
- package/dist/bridge/reply.js.map +1 -0
- package/dist/bridge/space-identity.d.ts +43 -0
- package/dist/bridge/space-identity.d.ts.map +1 -0
- package/dist/bridge/space-identity.js +92 -0
- package/dist/bridge/space-identity.js.map +1 -0
- package/dist/bridge/space-sync.d.ts +94 -0
- package/dist/bridge/space-sync.d.ts.map +1 -0
- package/dist/bridge/space-sync.js +137 -0
- package/dist/bridge/space-sync.js.map +1 -0
- package/dist/bridge/turn-commands.d.ts +28 -0
- package/dist/bridge/turn-commands.d.ts.map +1 -0
- package/dist/bridge/turn-commands.js +97 -0
- package/dist/bridge/turn-commands.js.map +1 -0
- package/dist/cli/config-store.d.ts +32 -0
- package/dist/cli/config-store.d.ts.map +1 -0
- package/dist/cli/config-store.js +118 -0
- package/dist/cli/config-store.js.map +1 -0
- package/dist/cli/crypto-store.d.ts +42 -0
- package/dist/cli/crypto-store.d.ts.map +1 -0
- package/dist/cli/crypto-store.js +70 -0
- package/dist/cli/crypto-store.js.map +1 -0
- package/dist/cli/device-prune.d.ts +105 -0
- package/dist/cli/device-prune.d.ts.map +1 -0
- package/dist/cli/device-prune.js +163 -0
- package/dist/cli/device-prune.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +584 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/log-filter.d.ts +32 -0
- package/dist/cli/log-filter.d.ts.map +1 -0
- package/dist/cli/log-filter.js +40 -0
- package/dist/cli/log-filter.js.map +1 -0
- package/dist/cli/pnpm-builds.d.ts +32 -0
- package/dist/cli/pnpm-builds.d.ts.map +1 -0
- package/dist/cli/pnpm-builds.js +73 -0
- package/dist/cli/pnpm-builds.js.map +1 -0
- package/dist/cli/profile-patch.d.ts +26 -0
- package/dist/cli/profile-patch.d.ts.map +1 -0
- package/dist/cli/profile-patch.js +56 -0
- package/dist/cli/profile-patch.js.map +1 -0
- package/dist/cli/setup.d.ts +39 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +234 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/systemd-hint.d.ts +11 -0
- package/dist/cli/systemd-hint.d.ts.map +1 -0
- package/dist/cli/systemd-hint.js +46 -0
- package/dist/cli/systemd-hint.js.map +1 -0
- package/dist/cli/systemd.d.ts +32 -0
- package/dist/cli/systemd.d.ts.map +1 -0
- package/dist/cli/systemd.js +58 -0
- package/dist/cli/systemd.js.map +1 -0
- package/dist/config.d.ts +54 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +107 -0
- package/dist/config.js.map +1 -0
- package/dist/dsh/backend.d.ts +110 -0
- package/dist/dsh/backend.d.ts.map +1 -0
- package/dist/dsh/backend.js +481 -0
- package/dist/dsh/backend.js.map +1 -0
- package/dist/dsh/interactions.d.ts +50 -0
- package/dist/dsh/interactions.d.ts.map +1 -0
- package/dist/dsh/interactions.js +141 -0
- package/dist/dsh/interactions.js.map +1 -0
- package/dist/dsh/stream.d.ts +32 -0
- package/dist/dsh/stream.d.ts.map +1 -0
- package/dist/dsh/stream.js +109 -0
- package/dist/dsh/stream.js.map +1 -0
- package/dist/formatting.d.ts +14 -0
- package/dist/formatting.d.ts.map +1 -0
- package/dist/formatting.js +63 -0
- package/dist/formatting.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +232 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +28 -0
- package/dist/logger.js.map +1 -0
- package/dist/matrix/matrix-events.d.ts +49 -0
- package/dist/matrix/matrix-events.d.ts.map +1 -0
- package/dist/matrix/matrix-events.js +89 -0
- package/dist/matrix/matrix-events.js.map +1 -0
- package/dist/matrix/transport.d.ts +192 -0
- package/dist/matrix/transport.d.ts.map +1 -0
- package/dist/matrix/transport.js +510 -0
- package/dist/matrix/transport.js.map +1 -0
- package/dist/ports/attachments.d.ts +51 -0
- package/dist/ports/attachments.d.ts.map +1 -0
- package/dist/ports/attachments.js +27 -0
- package/dist/ports/attachments.js.map +1 -0
- package/dist/ports/backend.d.ts +159 -0
- package/dist/ports/backend.d.ts.map +1 -0
- package/dist/ports/backend.js +25 -0
- package/dist/ports/backend.js.map +1 -0
- package/dist/ports/interactions.d.ts +65 -0
- package/dist/ports/interactions.d.ts.map +1 -0
- package/dist/ports/interactions.js +15 -0
- package/dist/ports/interactions.js.map +1 -0
- package/dist/ports/streaming.d.ts +45 -0
- package/dist/ports/streaming.d.ts.map +1 -0
- package/dist/ports/streaming.js +23 -0
- package/dist/ports/streaming.js.map +1 -0
- package/dist/ports/transport.d.ts +68 -0
- package/dist/ports/transport.d.ts.map +1 -0
- package/dist/ports/transport.js +2 -0
- package/dist/ports/transport.js.map +1 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface InstanceLock {
|
|
2
|
+
readonly path: string;
|
|
3
|
+
release(): void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 抢一个单实例锁。成功返回锁句柄;已有活锁时抛错(含持有者 pid)。
|
|
7
|
+
* 进程崩溃留下的陈旧锁(持有者 pid 已不存在)会被清掉后重抢一次。
|
|
8
|
+
*/
|
|
9
|
+
export declare function acquireInstanceLock(lockPath: string, pid?: number): InstanceLock;
|
|
10
|
+
//# sourceMappingURL=instance-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-lock.d.ts","sourceRoot":"","sources":["../../src/bridge/instance-lock.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,IAAI,IAAI,CAAA;CAChB;AA6BD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAoB,GAAG,YAAY,CAyC7F"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 桥单实例锁(规格实现决策 10 的 lock.ts)。
|
|
3
|
+
*
|
|
4
|
+
* 目的:两个 `dsh --profile <bridge>` 同时连同一个 Matrix 账号会**双回帖**、
|
|
5
|
+
* 互相抢会话,必须在启动时挡住。这里用 `open(path, 'wx')` 原子抢锁;
|
|
6
|
+
* 进程被 kill -9 留下的陈旧锁,用"持有者 pid 是否还活着"判定并清理。
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
function readHolder(lockPath) {
|
|
11
|
+
try {
|
|
12
|
+
const raw = JSON.parse(fs.readFileSync(lockPath, 'utf-8'));
|
|
13
|
+
if (typeof raw.pid !== 'number')
|
|
14
|
+
return undefined;
|
|
15
|
+
return { pid: raw.pid, ...(typeof raw.startedAt === 'string' ? { startedAt: raw.startedAt } : {}) };
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// 文件为空/坏 JSON:当作"持有者信息不可读",不贸然删除(可能是别的进程
|
|
19
|
+
// 刚 open 还没 write 的窗口期)。这种情况按"占用"处理,给用户明确报错。
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function isAlive(pid) {
|
|
24
|
+
try {
|
|
25
|
+
process.kill(pid, 0);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
// EPERM = 进程存在但没有权限发信号,仍算活着。
|
|
30
|
+
return err.code === 'EPERM';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 抢一个单实例锁。成功返回锁句柄;已有活锁时抛错(含持有者 pid)。
|
|
35
|
+
* 进程崩溃留下的陈旧锁(持有者 pid 已不存在)会被清掉后重抢一次。
|
|
36
|
+
*/
|
|
37
|
+
export function acquireInstanceLock(lockPath, pid = process.pid) {
|
|
38
|
+
fs.mkdirSync(path.dirname(lockPath), { recursive: true });
|
|
39
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
40
|
+
try {
|
|
41
|
+
const fd = fs.openSync(lockPath, 'wx');
|
|
42
|
+
try {
|
|
43
|
+
fs.writeSync(fd, JSON.stringify({ pid, startedAt: new Date().toISOString() }));
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
fs.closeSync(fd);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
path: lockPath,
|
|
50
|
+
release: () => {
|
|
51
|
+
try {
|
|
52
|
+
fs.unlinkSync(lockPath);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// 锁已被删(例如启动失败回滚)= 幂等,不抛。
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err.code !== 'EEXIST')
|
|
62
|
+
throw err;
|
|
63
|
+
const holder = readHolder(lockPath);
|
|
64
|
+
if (holder !== undefined && !isAlive(holder.pid)) {
|
|
65
|
+
try {
|
|
66
|
+
fs.unlinkSync(lockPath);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// 别的进程抢先清理了;下一轮循环按 EEXIST 重新判定。
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const who = holder
|
|
74
|
+
? `pid ${holder.pid}${holder.startedAt ? `(启动于 ${holder.startedAt})` : ''}`
|
|
75
|
+
: '持有者信息不可读(可能正在启动,或锁文件损坏)';
|
|
76
|
+
throw new Error(`已有另一个 dsh-matrix 桥实例在运行:${who}。同一个 Matrix 账号只允许一个桥实例,` +
|
|
77
|
+
`同时运行会双回帖。确认旧进程已停止后删除 ${lockPath} 再启动。`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
throw new Error(`无法获取单实例锁 ${lockPath}:陈旧锁反复出现或被并发争用,请稍后重试。`);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=instance-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-lock.js","sourceRoot":"","sources":["../../src/bridge/instance-lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge-side interaction orchestrator (T5): 把 agent 的提问与沙箱审批渲染到
|
|
3
|
+
* 房间,并让房间的下一条普通消息成为答案。
|
|
4
|
+
*
|
|
5
|
+
* 答案解析语义对齐 pi-courier(extensionCapture / parseExtensionUIAnswer):
|
|
6
|
+
* - 「取消」精确匹配(去首尾空白)= 放弃;
|
|
7
|
+
* - 选择题:数字序号(多选支持 1,2 / 1、2 / "1 2");y/n 在两选项题上快捷
|
|
8
|
+
* 映射(若选项里本来就有 Yes/No 标签则精确匹配标签);其余文本作为 custom
|
|
9
|
+
* 自由回答(dsh 的答案词汇支持 custom);
|
|
10
|
+
* - 输入题(无选项):整条消息即答案;
|
|
11
|
+
* - 斜杠命令永不被答案消费(仍走命令行)。
|
|
12
|
+
*/
|
|
13
|
+
import type { IncomingMessage, Logger } from '../types.ts';
|
|
14
|
+
import type { ApprovalOutcome, ApprovalRequestEvent, InteractionSource, QuestionItem } from '../ports/interactions.ts';
|
|
15
|
+
import type { Transport } from '../ports/transport.ts';
|
|
16
|
+
/** answerFromText 的三态结果:invalid 时留在队列里重新追问,不出队。 */
|
|
17
|
+
export type AnswerParse = {
|
|
18
|
+
kind: 'cancel';
|
|
19
|
+
} | {
|
|
20
|
+
kind: 'answered';
|
|
21
|
+
selected: string[];
|
|
22
|
+
custom?: string;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'invalid';
|
|
25
|
+
hint: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function answerFromText(question: QuestionItem, text: string): AnswerParse;
|
|
28
|
+
export type ApprovalParse = {
|
|
29
|
+
kind: 'cancel';
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'outcome';
|
|
32
|
+
outcome: ApprovalOutcome;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'invalid';
|
|
35
|
+
hint: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function parseApprovalAnswer(text: string): ApprovalParse;
|
|
38
|
+
/** 渲染当前这道子题(多题请求按序追问,题头带 (i/n) 定位)。 */
|
|
39
|
+
export declare function questionText(question: QuestionItem, index: number, total: number): string;
|
|
40
|
+
/** 渲染一条沙箱审批。 */
|
|
41
|
+
export declare function approvalText(event: ApprovalRequestEvent): string;
|
|
42
|
+
/** 提问自动取消的默认时限:10 分钟(pi-courier extensionUiTimeoutMinutes 同源)。 */
|
|
43
|
+
export declare const DEFAULT_INTERACTION_TIMEOUT_MS: number;
|
|
44
|
+
export interface InteractionsDeps {
|
|
45
|
+
transport: Transport;
|
|
46
|
+
logger: Logger;
|
|
47
|
+
source: InteractionSource;
|
|
48
|
+
/** 归属判定:桥会话 id → 房间;undefined = 不是桥的会话。 */
|
|
49
|
+
roomForSession(sessionId: string): string | undefined;
|
|
50
|
+
/** 超时毫秒(默认 10 分钟)。 */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
/** 可注入时钟:返回取消器。默认 setTimeout(+unref,绝不让挂起问题吊住进程)。 */
|
|
53
|
+
schedule?: (fn: () => void, ms: number) => () => void;
|
|
54
|
+
}
|
|
55
|
+
export interface Interactions {
|
|
56
|
+
/** pipeline intercept 挂点:该消息是否被挂起的问题/审批消费。 */
|
|
57
|
+
intercept(msg: IncomingMessage): Promise<boolean>;
|
|
58
|
+
/** 退场:收掉所有在途请求(按取消语义),不再消费消息。 */
|
|
59
|
+
stop(): void;
|
|
60
|
+
}
|
|
61
|
+
export declare function createInteractions(deps: InteractionsDeps): Interactions;
|
|
62
|
+
//# sourceMappingURL=interactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/bridge/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,KAAK,EACV,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EACpC,YAAY,EACjC,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtD,mDAAmD;AACnD,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAYrC,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAwChF;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAErC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAO/D;AAED,uCAAuC;AACvC,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBzF;AAED,gBAAgB;AAChB,wBAAgB,YAAY,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAKhE;AAsBD,kEAAkE;AAClE,eAAO,MAAM,8BAA8B,QAAc,CAAA;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,iBAAiB,CAAA;IACzB,2CAA2C;IAC3C,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACrD,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,IAAI,CAAA;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACjD,iCAAiC;IACjC,IAAI,IAAI,IAAI,CAAA;CACb;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAmJvE"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
const CANCEL_WORD = '取消';
|
|
2
|
+
const YES_WORDS = new Set(['y', 'yes']);
|
|
3
|
+
const NO_WORDS = new Set(['n', 'no']);
|
|
4
|
+
/** 折叠空白并截断(房间不是倾倒场)。 */
|
|
5
|
+
function oneLine(text, max) {
|
|
6
|
+
const collapsed = text.replace(/\s+/g, ' ').trim();
|
|
7
|
+
return collapsed.length > max ? `${collapsed.slice(0, max)}…` : collapsed;
|
|
8
|
+
}
|
|
9
|
+
export function answerFromText(question, text) {
|
|
10
|
+
const trimmed = text.trim();
|
|
11
|
+
if (trimmed === CANCEL_WORD)
|
|
12
|
+
return { kind: 'cancel' };
|
|
13
|
+
const options = question.options ?? [];
|
|
14
|
+
if (options.length === 0) {
|
|
15
|
+
// 输入题:整条消息就是答案(原文不折叠,保留用户排版)。
|
|
16
|
+
return { kind: 'answered', selected: [], custom: text };
|
|
17
|
+
}
|
|
18
|
+
// 纯序号(可多选):1 / "1,3" / "1、2" / "1 2"
|
|
19
|
+
const SEPS = /[,,、;;\s]+/;
|
|
20
|
+
const nums = trimmed.match(/^\d+(?:[,,、;;\s]+\d+)*$/);
|
|
21
|
+
if (nums) {
|
|
22
|
+
const picked = [...new Set(trimmed.split(SEPS).map(Number))];
|
|
23
|
+
const labels = picked.map((n) => options[n - 1]?.label);
|
|
24
|
+
const valid = picked.length > 0 && picked.every((n, i) => n >= 1 && labels[i] !== undefined);
|
|
25
|
+
if (!valid) {
|
|
26
|
+
return { kind: 'invalid', hint: `⚠️ 请回复 1 到 ${options.length} 之间的序号(发送「取消」放弃)` };
|
|
27
|
+
}
|
|
28
|
+
if (!question.multiSelect && picked.length > 1) {
|
|
29
|
+
return { kind: 'invalid', hint: '⚠️ 本题只能选一个,请只回复一个序号' };
|
|
30
|
+
}
|
|
31
|
+
return { kind: 'answered', selected: labels };
|
|
32
|
+
}
|
|
33
|
+
const lower = trimmed.toLowerCase();
|
|
34
|
+
const yesNo = YES_WORDS.has(lower) ? 'yes' : NO_WORDS.has(lower) ? 'no' : undefined;
|
|
35
|
+
if (yesNo) {
|
|
36
|
+
// 1) 选项里本来就有 yes/no 字样标签 → 精确匹配,不看顺序
|
|
37
|
+
const wanted = yesNo === 'yes' ? YES_WORDS : NO_WORDS;
|
|
38
|
+
const exact = options.find((o) => wanted.has(o.label.trim().toLowerCase()));
|
|
39
|
+
if (exact)
|
|
40
|
+
return { kind: 'answered', selected: [exact.label] };
|
|
41
|
+
// 2) 典型的是/否二选一 → y 第一个,n 第二个
|
|
42
|
+
if (options.length === 2) {
|
|
43
|
+
const pick = options[yesNo === 'yes' ? 0 : 1];
|
|
44
|
+
if (pick)
|
|
45
|
+
return { kind: 'answered', selected: [pick.label] };
|
|
46
|
+
}
|
|
47
|
+
// 3) 其余:「y」只是普通自由文本
|
|
48
|
+
}
|
|
49
|
+
// 自由文本兜底:dsh 词汇里 custom 即"不满意选项,用户另有说法"。
|
|
50
|
+
return { kind: 'answered', selected: [], custom: trimmed };
|
|
51
|
+
}
|
|
52
|
+
export function parseApprovalAnswer(text) {
|
|
53
|
+
const trimmed = text.trim();
|
|
54
|
+
if (trimmed === CANCEL_WORD)
|
|
55
|
+
return { kind: 'cancel' };
|
|
56
|
+
const lower = trimmed.toLowerCase();
|
|
57
|
+
if (YES_WORDS.has(lower))
|
|
58
|
+
return { kind: 'outcome', outcome: 'allowed-once' };
|
|
59
|
+
if (NO_WORDS.has(lower))
|
|
60
|
+
return { kind: 'outcome', outcome: 'rejected' };
|
|
61
|
+
return { kind: 'invalid', hint: '⚠️ 审批请回复 y(允许一次)或 n(拒绝),发送「取消」放弃' };
|
|
62
|
+
}
|
|
63
|
+
/** 渲染当前这道子题(多题请求按序追问,题头带 (i/n) 定位)。 */
|
|
64
|
+
export function questionText(question, index, total) {
|
|
65
|
+
const loc = total > 1 ? ` (${index + 1}/${total})` : '';
|
|
66
|
+
const head = question.header ? `【${oneLine(question.header, 40)}】` : '';
|
|
67
|
+
const lines = [`❓ ${head}${oneLine(question.question, 300)}${loc}`];
|
|
68
|
+
if (question.detail)
|
|
69
|
+
lines.push(oneLine(question.detail, 500));
|
|
70
|
+
const options = question.options ?? [];
|
|
71
|
+
if (options.length > 0) {
|
|
72
|
+
lines.push(...options.map((o, i) => `${i + 1}. ${o.label}${o.description ? ` —— ${oneLine(o.description, 120)}` : ''}`));
|
|
73
|
+
lines.push(question.multiSelect
|
|
74
|
+
? '回复序号选择,可多个(如 1、3),也可回复自由内容(发送「取消」放弃)'
|
|
75
|
+
: '回复序号选择,也可直接回复其他内容作为自定义答案(发送「取消」放弃)');
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
lines.push('直接回复内容作为答案(发送「取消」放弃)');
|
|
79
|
+
}
|
|
80
|
+
return lines.join('\n');
|
|
81
|
+
}
|
|
82
|
+
/** 渲染一条沙箱审批。 */
|
|
83
|
+
export function approvalText(event) {
|
|
84
|
+
const lines = [`🔐 沙箱审批:agent 请求执行工具 ${event.toolName}`];
|
|
85
|
+
if (event.reason)
|
|
86
|
+
lines.push(`原因:${oneLine(event.reason, 300)}`);
|
|
87
|
+
lines.push('回复 y 允许一次 / n 拒绝(发送「取消」放弃)');
|
|
88
|
+
return lines.join('\n');
|
|
89
|
+
}
|
|
90
|
+
/** 提问自动取消的默认时限:10 分钟(pi-courier extensionUiTimeoutMinutes 同源)。 */
|
|
91
|
+
export const DEFAULT_INTERACTION_TIMEOUT_MS = 10 * 60_000;
|
|
92
|
+
export function createInteractions(deps) {
|
|
93
|
+
const { transport, logger } = deps;
|
|
94
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_INTERACTION_TIMEOUT_MS;
|
|
95
|
+
const schedule = deps.schedule ?? ((fn, ms) => {
|
|
96
|
+
const timer = setTimeout(fn, ms);
|
|
97
|
+
timer.unref?.();
|
|
98
|
+
return () => clearTimeout(timer);
|
|
99
|
+
});
|
|
100
|
+
// 单一到达顺序队列(与 pi-courier 一致):同房间的问题与审批先到先答,
|
|
101
|
+
// 不同房间互不串台(intercept 只找自己房头的挂起项)。
|
|
102
|
+
const queue = [];
|
|
103
|
+
let stopped = false;
|
|
104
|
+
function title(entry) {
|
|
105
|
+
return entry.kind === 'question'
|
|
106
|
+
? oneLine(entry.event.questions[entry.index]?.question ?? '问题', 80)
|
|
107
|
+
: `审批 ${entry.event.toolName}`;
|
|
108
|
+
}
|
|
109
|
+
/** 出队并兑现取消语义:问题=全部跳过答案,审批=cancelled;quiet 用于 signal 中断。 */
|
|
110
|
+
function expire(entry, notice) {
|
|
111
|
+
const i = queue.indexOf(entry);
|
|
112
|
+
if (i === -1)
|
|
113
|
+
return; // 已被答案/取消处理
|
|
114
|
+
queue.splice(i, 1);
|
|
115
|
+
entry.cancelTimer();
|
|
116
|
+
if (entry.kind === 'question') {
|
|
117
|
+
entry.respond(entry.event.questions.map((q) => ({ id: q.id, selected: [] })));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
entry.respond('cancelled');
|
|
121
|
+
}
|
|
122
|
+
if (notice)
|
|
123
|
+
transport.notify(entry.roomId, notice).catch(() => { });
|
|
124
|
+
}
|
|
125
|
+
function enqueue(entry, render) {
|
|
126
|
+
queue.push(entry);
|
|
127
|
+
if (entry.event.signal?.aborted) {
|
|
128
|
+
expire(entry, null); // 到手即已中断:静默收场
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
entry.event.signal?.addEventListener('abort', () => expire(entry, null));
|
|
132
|
+
entry.cancelTimer = schedule(() => expire(entry, `⌛ 「${title(entry)}」超时未答,已按取消处理`), timeoutMs);
|
|
133
|
+
transport.send(entry.roomId, render)
|
|
134
|
+
.catch((error) => logger.warn('interactions render failed:', error instanceof Error ? error.message : error));
|
|
135
|
+
}
|
|
136
|
+
const unsubscribeQuestion = deps.source.onRequestQuestion((event, respond) => {
|
|
137
|
+
if (stopped)
|
|
138
|
+
return respond(event.questions.map((q) => ({ id: q.id, selected: [] })));
|
|
139
|
+
const roomId = deps.roomForSession(event.sessionId);
|
|
140
|
+
if (!roomId) {
|
|
141
|
+
// 防御:source 已过滤,真到这里的只可能是归属表没跟上——按跳过收场,别留悬案
|
|
142
|
+
logger.warn(`interactions: session ${event.sessionId} 无归属房间,提问按跳过处理`);
|
|
143
|
+
respond(event.questions.map((q) => ({ id: q.id, selected: [] })));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const entry = {
|
|
147
|
+
kind: 'question', roomId, event, index: 0, answers: [], respond, cancelTimer: () => { },
|
|
148
|
+
};
|
|
149
|
+
enqueue(entry, questionText(event.questions[0], 0, event.questions.length));
|
|
150
|
+
});
|
|
151
|
+
const unsubscribeApproval = deps.source.onRequestApproval((event, respond) => {
|
|
152
|
+
if (stopped)
|
|
153
|
+
return respond('cancelled');
|
|
154
|
+
const roomId = deps.roomForSession(event.sessionId);
|
|
155
|
+
if (!roomId) {
|
|
156
|
+
logger.warn(`interactions: session ${event.sessionId} 无归属房间,审批按 cancelled 处理`);
|
|
157
|
+
respond('cancelled');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const entry = { kind: 'approval', roomId, event, respond, cancelTimer: () => { } };
|
|
161
|
+
enqueue(entry, approvalText(event));
|
|
162
|
+
});
|
|
163
|
+
async function interceptQuestion(entry, msg) {
|
|
164
|
+
const text = msg.text.trim();
|
|
165
|
+
const question = entry.event.questions[entry.index];
|
|
166
|
+
const parsed = answerFromText(question, text);
|
|
167
|
+
if (parsed.kind === 'invalid') {
|
|
168
|
+
await transport.notify(entry.roomId, parsed.hint);
|
|
169
|
+
return true; // 消息确实是冲着问题来的:消费掉,重新追问
|
|
170
|
+
}
|
|
171
|
+
if (parsed.kind === 'cancel') {
|
|
172
|
+
expire(entry, '已取消');
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
entry.answers.push({
|
|
176
|
+
id: question.id,
|
|
177
|
+
selected: parsed.selected,
|
|
178
|
+
...(parsed.custom !== undefined ? { custom: parsed.custom } : {}),
|
|
179
|
+
});
|
|
180
|
+
entry.index += 1;
|
|
181
|
+
if (entry.index < entry.event.questions.length) {
|
|
182
|
+
// 多题批次:entry 留在队列原位,只推进到下一道子题(重新计时)。
|
|
183
|
+
entry.cancelTimer();
|
|
184
|
+
entry.cancelTimer = schedule(() => expire(entry, `⌛ 「${title(entry)}」超时未答,已按取消处理`), timeoutMs);
|
|
185
|
+
await transport.notify(entry.roomId, `✅ 已记录(${entry.index}/${entry.event.questions.length})`);
|
|
186
|
+
await transport.send(entry.roomId, questionText(entry.event.questions[entry.index], entry.index, entry.event.questions.length));
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
queue.splice(queue.indexOf(entry), 1);
|
|
190
|
+
entry.cancelTimer();
|
|
191
|
+
await transport.notify(entry.roomId, '✅ 已回应');
|
|
192
|
+
entry.respond(entry.answers);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
async function intercept(msg) {
|
|
196
|
+
if (stopped)
|
|
197
|
+
return false;
|
|
198
|
+
const text = msg.text.trim();
|
|
199
|
+
if (!text)
|
|
200
|
+
return false;
|
|
201
|
+
if (text.startsWith('/'))
|
|
202
|
+
return false; // 斜杠仍走命令,只有普通文本才被问题消费
|
|
203
|
+
const entry = queue.find((e) => e.roomId === msg.roomId);
|
|
204
|
+
if (!entry)
|
|
205
|
+
return false;
|
|
206
|
+
if (entry.kind === 'approval') {
|
|
207
|
+
const parsed = parseApprovalAnswer(text);
|
|
208
|
+
if (parsed.kind === 'invalid') {
|
|
209
|
+
await transport.notify(entry.roomId, parsed.hint);
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
if (parsed.kind === 'cancel') {
|
|
213
|
+
expire(entry, '已取消');
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
queue.splice(queue.indexOf(entry), 1);
|
|
217
|
+
entry.cancelTimer();
|
|
218
|
+
await transport.notify(entry.roomId, '✅ 已回应');
|
|
219
|
+
entry.respond(parsed.outcome);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return interceptQuestion(entry, msg);
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
intercept,
|
|
226
|
+
stop() {
|
|
227
|
+
if (stopped)
|
|
228
|
+
return;
|
|
229
|
+
stopped = true;
|
|
230
|
+
unsubscribeQuestion();
|
|
231
|
+
unsubscribeApproval();
|
|
232
|
+
for (const entry of [...queue])
|
|
233
|
+
expire(entry, null);
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=interactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.js","sourceRoot":"","sources":["../../src/bridge/interactions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T9(最小版):管理房间的用户可见文案 —— 移植 pi-courier management-room.ts,
|
|
3
|
+
* 去掉本票不做的空间/头像部分(T12 空间票再接)。单一组装点,收养路径与
|
|
4
|
+
* (未来)启动 ensure 都从这里取文案,永不漂移。
|
|
5
|
+
*/
|
|
6
|
+
/** 管理房间显示名:项目管理(<实例名>)。 */
|
|
7
|
+
export declare function managementRoomName(instanceName: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* 管理房间使用指南。直接发消息 = 在默认工作目录对话;/pmctl 五操作仅本房可用。
|
|
10
|
+
* botAccount 未知时传空串,该行自动省略。
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildManagementRoomHelp(instanceName: string, botAccount: string, workdir: string): string;
|
|
13
|
+
//# sourceMappingURL=management-room.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"management-room.d.ts","sourceRoot":"","sources":["../../src/bridge/management-room.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2BAA2B;AAC3B,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,MAAM,CAcR"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T9(最小版):管理房间的用户可见文案 —— 移植 pi-courier management-room.ts,
|
|
3
|
+
* 去掉本票不做的空间/头像部分(T12 空间票再接)。单一组装点,收养路径与
|
|
4
|
+
* (未来)启动 ensure 都从这里取文案,永不漂移。
|
|
5
|
+
*/
|
|
6
|
+
/** 管理房间显示名:项目管理(<实例名>)。 */
|
|
7
|
+
export function managementRoomName(instanceName) {
|
|
8
|
+
return `项目管理(${instanceName})`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 管理房间使用指南。直接发消息 = 在默认工作目录对话;/pmctl 五操作仅本房可用。
|
|
12
|
+
* botAccount 未知时传空串,该行自动省略。
|
|
13
|
+
*/
|
|
14
|
+
export function buildManagementRoomHelp(instanceName, botAccount, workdir) {
|
|
15
|
+
return (`🏗️ **项目管理房间**(${instanceName})\n\n` +
|
|
16
|
+
(botAccount ? `• bot 账号: \`${botAccount}\`\n` : '') +
|
|
17
|
+
`• 默认工作目录: \`${workdir}\`\n\n` +
|
|
18
|
+
`这里是本实例的管理台。直接发消息 = 在默认项目(${workdir})里与 agent 对话。\n\n` +
|
|
19
|
+
`📁 **项目管理**(仅本房间可用)\n` +
|
|
20
|
+
`• \`/pmctl new <名称> [路径]\` — 创建项目(自动建私有房间并拉你进入)\n` +
|
|
21
|
+
`• \`/pmctl list\` — 项目列表\n` +
|
|
22
|
+
`• \`/pmctl show|rm|mv|rename\` — 项目详情/删除/迁移/重命名\n\n` +
|
|
23
|
+
`⚡ **常用命令**\n` +
|
|
24
|
+
`• \`/stop\` — 停止当前任务\n` +
|
|
25
|
+
`• \`/help\` — 完整帮助`);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=management-room.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"management-room.js","sourceRoot":"","sources":["../../src/bridge/management-room.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2BAA2B;AAC3B,MAAM,UAAU,kBAAkB,CAAC,YAAoB;IACrD,OAAO,QAAQ,YAAY,GAAG,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,YAAoB,EACpB,UAAkB,EAClB,OAAe;IAEf,OAAO,CACL,kBAAkB,YAAY,OAAO;QACrC,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,eAAe,OAAO,QAAQ;QAC9B,4BAA4B,OAAO,mBAAmB;QACtD,uBAAuB;QACvB,mDAAmD;QACnD,4BAA4B;QAC5B,qDAAqD;QACrD,cAAc;QACd,wBAAwB;QACxB,oBAAoB,CACrB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T9: 多项目装配 —— 把 ProjectMap(映射)、管理房间收养(Transport 改名 +
|
|
3
|
+
* 指南)、PmctlController(/pmctl 五操作)组合成 pipeline 需要的两个挂点:
|
|
4
|
+
* - resolveCwd(roomId):项目房 → 其 workdir;其余 → 缺省工程根。
|
|
5
|
+
* - multiProject:{ adoptRoom, isManagementRoom, handlePmctl }。
|
|
6
|
+
*
|
|
7
|
+
* 单项目模式(multiProject=false 或无映射)下 resolveCwd 恒返回
|
|
8
|
+
* defaultWorkdir、multiProject=undefined —— pipeline 现行为逐条不变。
|
|
9
|
+
*/
|
|
10
|
+
import type { Backend } from '../ports/backend.ts';
|
|
11
|
+
import type { Transport } from '../ports/transport.ts';
|
|
12
|
+
import type { Logger } from '../types.ts';
|
|
13
|
+
import type { BridgeDeps } from './pipeline.ts';
|
|
14
|
+
import type { ProjectMap } from './projects.ts';
|
|
15
|
+
export interface MultiProjectWiringConfig {
|
|
16
|
+
/** 映射持久层;单项目模式可不给(此时恒等同现行为)。 */
|
|
17
|
+
map?: ProjectMap;
|
|
18
|
+
transport: Transport;
|
|
19
|
+
backend: Backend;
|
|
20
|
+
logger: Logger;
|
|
21
|
+
multiProject: boolean;
|
|
22
|
+
instanceName: string;
|
|
23
|
+
defaultWorkdir: string;
|
|
24
|
+
/** T12(US37):建房后按账本提权的挂钩(见 PmctlDeps.onRoomCreated)。 */
|
|
25
|
+
onRoomCreated?: (roomId: string) => Promise<void>;
|
|
26
|
+
/** 两步确认/超时用的时钟(测试注入假时钟)。 */
|
|
27
|
+
now?: () => number;
|
|
28
|
+
}
|
|
29
|
+
export interface MultiProjectWiring {
|
|
30
|
+
resolveCwd: (roomId: string) => string;
|
|
31
|
+
multiProject?: NonNullable<BridgeDeps['multiProject']>;
|
|
32
|
+
}
|
|
33
|
+
export declare function createMultiProjectWiring(cfg: MultiProjectWiringConfig): MultiProjectWiring;
|
|
34
|
+
//# sourceMappingURL=multi-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-project.d.ts","sourceRoot":"","sources":["../../src/bridge/multi-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAmB,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAI/C,MAAM,WAAW,wBAAwB;IACvC,gCAAgC;IAChC,GAAG,CAAC,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,wDAAwD;IACxD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC,YAAY,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAA;CACvD;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,wBAAwB,GAAG,kBAAkB,CA2C1F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { PmctlController } from "./pmctl.js";
|
|
2
|
+
import { buildManagementRoomHelp, managementRoomName } from "./management-room.js";
|
|
3
|
+
export function createMultiProjectWiring(cfg) {
|
|
4
|
+
if (!cfg.multiProject || !cfg.map) {
|
|
5
|
+
return { resolveCwd: () => cfg.defaultWorkdir };
|
|
6
|
+
}
|
|
7
|
+
const map = cfg.map;
|
|
8
|
+
const controller = new PmctlController({
|
|
9
|
+
map,
|
|
10
|
+
transport: cfg.transport,
|
|
11
|
+
backend: cfg.backend,
|
|
12
|
+
logger: cfg.logger,
|
|
13
|
+
instanceName: cfg.instanceName,
|
|
14
|
+
multiProject: true,
|
|
15
|
+
...(cfg.onRoomCreated ? { onRoomCreated: cfg.onRoomCreated } : {}),
|
|
16
|
+
...(cfg.now ? { now: cfg.now } : {}),
|
|
17
|
+
});
|
|
18
|
+
async function adoptRoom(msg) {
|
|
19
|
+
// 收养条件:私聊 + 非项目房 + 尚未定管理房(已定就不动 → 幂等)。
|
|
20
|
+
if (!msg.isDm || map.isProjectRoom(msg.roomId) || map.managementRoom() !== undefined)
|
|
21
|
+
return;
|
|
22
|
+
if (!cfg.transport.setRoomName)
|
|
23
|
+
return; // 无房间能力不收养(Matrix 之外)
|
|
24
|
+
try {
|
|
25
|
+
await cfg.transport.setRoomName(msg.roomId, managementRoomName(cfg.instanceName));
|
|
26
|
+
await cfg.transport.send(msg.roomId, buildManagementRoomHelp(cfg.instanceName, cfg.transport.getBotUserId?.() ?? '', cfg.defaultWorkdir));
|
|
27
|
+
await map.adoptManagementRoom(msg.roomId);
|
|
28
|
+
cfg.logger.info(`管理房间已收养: ${msg.roomId}`);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
// 改名/发送失败:不持久化,下条 trusted 消息再试(蓝本 transient 语义)。
|
|
32
|
+
cfg.logger.warn('管理房间收养失败(稍后重试):', error instanceof Error ? error.message : error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
resolveCwd: (roomId) => map.get(roomId)?.workdir ?? cfg.defaultWorkdir,
|
|
37
|
+
multiProject: {
|
|
38
|
+
adoptRoom,
|
|
39
|
+
isManagementRoom: (roomId) => map.isManagementRoom(roomId),
|
|
40
|
+
handlePmctl: (text, call, reply) => controller.handle(text, call, reply),
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=multi-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-project.js","sourceRoot":"","sources":["../../src/bridge/multi-project.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAsBlF,MAAM,UAAU,wBAAwB,CAAC,GAA6B;IACpE,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QAClC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,cAAc,EAAE,CAAA;IACjD,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAA;IAEnB,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC;QACrC,GAAG;QACH,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,YAAY,EAAE,IAAI;QAClB,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrC,CAAC,CAAA;IAEF,KAAK,UAAU,SAAS,CAAC,GAAoB;QAC3C,uCAAuC;QACvC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,KAAK,SAAS;YAAE,OAAM;QAC5F,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW;YAAE,OAAM,CAAC,sBAAsB;QAC7D,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAA;YACjF,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CACtB,GAAG,CAAC,MAAM,EACV,uBAAuB,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,cAAc,CAAC,CACpG,CAAA;YACD,MAAM,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACzC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,iDAAiD;YACjD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QACpF,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,IAAI,GAAG,CAAC,cAAc;QACtE,YAAY,EAAE;YACZ,SAAS;YACT,gBAAgB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAC1D,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC;SACzE;KACF,CAAA;AACH,CAAC"}
|