u-foo 1.0.3 → 1.1.9
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/README.md +110 -11
- package/README.zh-CN.md +9 -7
- package/SKILLS/ufoo/SKILL.md +132 -0
- package/SKILLS/uinit/SKILL.md +78 -0
- package/SKILLS/ustatus/SKILL.md +36 -0
- package/bin/uclaude.js +13 -0
- package/bin/ucode-core.js +15 -0
- package/bin/ucode.js +125 -0
- package/bin/ucodex.js +13 -0
- package/bin/ufoo +9 -31
- package/bin/ufoo-assistant-agent.js +5 -0
- package/bin/ufoo-engine.js +25 -0
- package/bin/ufoo.js +17 -0
- package/modules/AGENTS.template.md +29 -11
- package/modules/bus/README.md +33 -25
- package/modules/bus/SKILLS/ubus/SKILL.md +19 -8
- package/modules/context/README.md +18 -40
- package/modules/context/SKILLS/uctx/SKILL.md +63 -1
- package/modules/online/SKILLS/ufoo-online/SKILL.md +144 -0
- package/package.json +25 -4
- package/scripts/import-pi-mono.js +124 -0
- package/scripts/postinstall.js +30 -0
- package/scripts/sync-claude-skills.sh +21 -0
- package/src/agent/cliRunner.js +554 -33
- package/src/agent/internalRunner.js +150 -56
- package/src/agent/launcher.js +754 -0
- package/src/agent/normalizeOutput.js +1 -1
- package/src/agent/notifier.js +340 -0
- package/src/agent/ptyRunner.js +847 -0
- package/src/agent/ptyWrapper.js +379 -0
- package/src/agent/readyDetector.js +175 -0
- package/src/agent/ucode.js +443 -0
- package/src/agent/ucodeBootstrap.js +113 -0
- package/src/agent/ucodeBuild.js +67 -0
- package/src/agent/ucodeDoctor.js +184 -0
- package/src/agent/ucodeRuntimeConfig.js +129 -0
- package/src/agent/ufooAgent.js +46 -42
- package/src/assistant/agent.js +260 -0
- package/src/assistant/bridge.js +172 -0
- package/src/assistant/engine.js +252 -0
- package/src/assistant/stdio.js +58 -0
- package/src/assistant/ufooEngineCli.js +306 -0
- package/src/bus/activate.js +172 -0
- package/src/bus/daemon.js +436 -0
- package/src/bus/index.js +842 -0
- package/src/bus/inject.js +315 -0
- package/src/bus/message.js +430 -0
- package/src/bus/nickname.js +88 -0
- package/src/bus/queue.js +136 -0
- package/src/bus/shake.js +26 -0
- package/src/bus/store.js +189 -0
- package/src/bus/subscriber.js +312 -0
- package/src/bus/utils.js +363 -0
- package/src/chat/agentBar.js +117 -0
- package/src/chat/agentDirectory.js +88 -0
- package/src/chat/agentSockets.js +225 -0
- package/src/chat/agentViewController.js +298 -0
- package/src/chat/chatLogController.js +115 -0
- package/src/chat/commandExecutor.js +700 -0
- package/src/chat/commands.js +132 -0
- package/src/chat/completionController.js +414 -0
- package/src/chat/cronScheduler.js +160 -0
- package/src/chat/daemonConnection.js +166 -0
- package/src/chat/daemonCoordinator.js +64 -0
- package/src/chat/daemonMessageRouter.js +257 -0
- package/src/chat/daemonReconnect.js +41 -0
- package/src/chat/daemonTransport.js +36 -0
- package/src/chat/daemonTransportDefaults.js +10 -0
- package/src/chat/dashboardKeyController.js +480 -0
- package/src/chat/dashboardView.js +154 -0
- package/src/chat/index.js +1011 -1392
- package/src/chat/inputHistoryController.js +105 -0
- package/src/chat/inputListenerController.js +304 -0
- package/src/chat/inputMath.js +104 -0
- package/src/chat/inputSubmitHandler.js +171 -0
- package/src/chat/layout.js +165 -0
- package/src/chat/pasteController.js +81 -0
- package/src/chat/rawKeyMap.js +42 -0
- package/src/chat/settingsController.js +132 -0
- package/src/chat/statusLineController.js +177 -0
- package/src/chat/streamTracker.js +138 -0
- package/src/chat/text.js +70 -0
- package/src/chat/transport.js +61 -0
- package/src/cli/busCoreCommands.js +59 -0
- package/src/cli/ctxCoreCommands.js +199 -0
- package/src/cli/onlineCoreCommands.js +379 -0
- package/src/cli.js +1162 -96
- package/src/code/README.md +29 -0
- package/src/code/UCODE_PROMPT.md +32 -0
- package/src/code/agent.js +1651 -0
- package/src/code/cli.js +158 -0
- package/src/code/config +0 -0
- package/src/code/dispatch.js +42 -0
- package/src/code/index.js +70 -0
- package/src/code/nativeRunner.js +1213 -0
- package/src/code/runtime.js +154 -0
- package/src/code/sessionStore.js +162 -0
- package/src/code/taskDecomposer.js +269 -0
- package/src/code/tools/bash.js +53 -0
- package/src/code/tools/common.js +42 -0
- package/src/code/tools/edit.js +70 -0
- package/src/code/tools/read.js +44 -0
- package/src/code/tools/write.js +35 -0
- package/src/code/tui.js +1580 -0
- package/src/config.js +56 -3
- package/src/context/decisions.js +324 -0
- package/src/context/doctor.js +183 -0
- package/src/context/index.js +55 -0
- package/src/context/sync.js +127 -0
- package/src/daemon/agentProcessManager.js +74 -0
- package/src/daemon/cronOps.js +241 -0
- package/src/daemon/index.js +998 -170
- package/src/daemon/ipcServer.js +99 -0
- package/src/daemon/ops.js +630 -48
- package/src/daemon/promptLoop.js +319 -0
- package/src/daemon/promptRequest.js +101 -0
- package/src/daemon/providerSessions.js +306 -0
- package/src/daemon/reporting.js +90 -0
- package/src/daemon/run.js +31 -1
- package/src/daemon/status.js +48 -8
- package/src/doctor/index.js +50 -0
- package/src/init/index.js +318 -0
- package/src/online/bridge.js +663 -0
- package/src/online/client.js +245 -0
- package/src/online/runner.js +253 -0
- package/src/online/server.js +992 -0
- package/src/online/tokens.js +103 -0
- package/src/report/store.js +331 -0
- package/src/shared/eventContract.js +35 -0
- package/src/shared/ptySocketContract.js +21 -0
- package/src/skills/index.js +159 -0
- package/src/status/index.js +285 -0
- package/src/terminal/adapterContract.js +87 -0
- package/src/terminal/adapterRouter.js +84 -0
- package/src/terminal/adapters/externalAdapter.js +14 -0
- package/src/terminal/adapters/internalAdapter.js +13 -0
- package/src/terminal/adapters/internalPtyAdapter.js +42 -0
- package/src/terminal/adapters/internalQueueAdapter.js +37 -0
- package/src/terminal/adapters/terminalAdapter.js +31 -0
- package/src/terminal/adapters/tmuxAdapter.js +30 -0
- package/src/terminal/detect.js +64 -0
- package/src/terminal/index.js +8 -0
- package/src/terminal/iterm2.js +126 -0
- package/src/ufoo/agentsStore.js +107 -0
- package/src/ufoo/paths.js +46 -0
- package/src/utils/banner.js +76 -0
- package/bin/uclaude +0 -65
- package/bin/ucodex +0 -65
- package/modules/bus/scripts/bus-alert.sh +0 -185
- package/modules/bus/scripts/bus-listen.sh +0 -117
- package/modules/context/ASSUMPTIONS.md +0 -7
- package/modules/context/CONSTRAINTS.md +0 -7
- package/modules/context/CONTEXT-STRUCTURE.md +0 -49
- package/modules/context/DECISION-PROTOCOL.md +0 -62
- package/modules/context/HANDOFF.md +0 -33
- package/modules/context/RULES.md +0 -15
- package/modules/context/SKILLS/README.md +0 -14
- package/modules/context/SYSTEM.md +0 -18
- package/modules/context/TEMPLATES/assumptions.md +0 -4
- package/modules/context/TEMPLATES/constraints.md +0 -4
- package/modules/context/TEMPLATES/decision.md +0 -16
- package/modules/context/TEMPLATES/project-context-readme.md +0 -6
- package/modules/context/TEMPLATES/system.md +0 -3
- package/modules/context/TEMPLATES/terminology.md +0 -4
- package/modules/context/TERMINOLOGY.md +0 -10
- package/scripts/banner.sh +0 -89
- package/scripts/bus-alert.sh +0 -6
- package/scripts/bus-autotrigger.sh +0 -6
- package/scripts/bus-daemon.sh +0 -231
- package/scripts/bus-inject.sh +0 -144
- package/scripts/bus-listen.sh +0 -6
- package/scripts/bus.sh +0 -984
- package/scripts/context-decisions.sh +0 -167
- package/scripts/context-doctor.sh +0 -72
- package/scripts/context-lint.sh +0 -110
- package/scripts/doctor.sh +0 -22
- package/scripts/init.sh +0 -247
- package/scripts/skills.sh +0 -113
- package/scripts/status.sh +0 -125
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const path = require("path");
|
|
3
|
+
const { getUfooPaths } = require("../ufoo/paths");
|
|
3
4
|
const { spawnSync } = require("child_process");
|
|
4
|
-
const
|
|
5
|
+
const EventBus = require("../bus");
|
|
5
6
|
const { runCliAgent } = require("./cliRunner");
|
|
6
7
|
const { normalizeCliOutput } = require("./normalizeOutput");
|
|
7
8
|
|
|
@@ -9,77 +10,114 @@ function sleep(ms) {
|
|
|
9
10
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
function generateSessionId() {
|
|
13
|
-
return randomBytes(4).toString("hex");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
13
|
function buildEnv(agentType, sessionId, publisher, nickname) {
|
|
17
14
|
const env = { ...process.env };
|
|
18
|
-
if (agentType === "codex") {
|
|
19
|
-
env.CODEX_SESSION_ID = sessionId;
|
|
20
|
-
env.CLAUDE_SESSION_ID = "";
|
|
21
|
-
} else {
|
|
22
|
-
env.CLAUDE_SESSION_ID = sessionId;
|
|
23
|
-
env.CODEX_SESSION_ID = "";
|
|
24
|
-
}
|
|
25
15
|
env.AI_BUS_PUBLISHER = publisher || env.AI_BUS_PUBLISHER || "";
|
|
26
16
|
env.UFOO_NICKNAME = nickname || env.UFOO_NICKNAME || "";
|
|
27
17
|
env.UFOO_PARENT_PID = String(process.pid);
|
|
28
18
|
return env;
|
|
29
19
|
}
|
|
30
20
|
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
throw new Error(err || "bus join failed");
|
|
21
|
+
function parseSubscriberId() {
|
|
22
|
+
// Daemon 已经注册,直接使用
|
|
23
|
+
if (process.env.UFOO_SUBSCRIBER_ID) {
|
|
24
|
+
const parts = process.env.UFOO_SUBSCRIBER_ID.split(":");
|
|
25
|
+
if (parts.length === 2) {
|
|
26
|
+
return {
|
|
27
|
+
subscriber: process.env.UFOO_SUBSCRIBER_ID,
|
|
28
|
+
agentType: parts[0],
|
|
29
|
+
sessionId: parts[1],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
43
32
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return { subscriber, env };
|
|
33
|
+
|
|
34
|
+
throw new Error("Internal runner requires UFOO_SUBSCRIBER_ID set by daemon");
|
|
47
35
|
}
|
|
48
36
|
|
|
49
37
|
function safeSubscriber(subscriber) {
|
|
50
38
|
return subscriber.replace(/:/g, "_");
|
|
51
39
|
}
|
|
52
40
|
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
41
|
+
function createBusSender(projectRoot, subscriber) {
|
|
42
|
+
const eventBus = new EventBus(projectRoot);
|
|
43
|
+
let sendQueue = Promise.resolve();
|
|
44
|
+
|
|
45
|
+
function enqueue(target, message) {
|
|
46
|
+
if (!target || !message) return;
|
|
47
|
+
sendQueue = sendQueue
|
|
48
|
+
.then(() => eventBus.send(target, message, subscriber))
|
|
49
|
+
.catch(() => {
|
|
50
|
+
// ignore per-message bus send errors to keep runner loop alive
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function flush() {
|
|
55
|
+
try {
|
|
56
|
+
await sendQueue;
|
|
57
|
+
} catch {
|
|
58
|
+
// ignore flush errors
|
|
59
|
+
}
|
|
61
60
|
}
|
|
61
|
+
|
|
62
|
+
return { enqueue, flush };
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
function
|
|
65
|
+
function drainQueue(queueFile) {
|
|
66
|
+
if (!fs.existsSync(queueFile)) return [];
|
|
67
|
+
const processingFile = `${queueFile}.processing.${process.pid}.${Date.now()}`;
|
|
68
|
+
let content = "";
|
|
69
|
+
let readOk = false;
|
|
65
70
|
try {
|
|
66
|
-
fs.
|
|
71
|
+
fs.renameSync(queueFile, processingFile);
|
|
72
|
+
content = fs.readFileSync(processingFile, "utf8");
|
|
73
|
+
readOk = true;
|
|
67
74
|
} catch {
|
|
68
|
-
|
|
75
|
+
try {
|
|
76
|
+
if (fs.existsSync(processingFile)) {
|
|
77
|
+
fs.renameSync(processingFile, queueFile);
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
// ignore rollback errors
|
|
81
|
+
}
|
|
82
|
+
return [];
|
|
83
|
+
} finally {
|
|
84
|
+
if (readOk) {
|
|
85
|
+
try {
|
|
86
|
+
if (fs.existsSync(processingFile)) {
|
|
87
|
+
fs.rmSync(processingFile, { force: true });
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// ignore cleanup errors
|
|
91
|
+
}
|
|
92
|
+
}
|
|
69
93
|
}
|
|
94
|
+
if (!content.trim()) return [];
|
|
95
|
+
return content.split(/\r?\n/).filter(Boolean);
|
|
70
96
|
}
|
|
71
97
|
|
|
72
|
-
async function handleEvent(projectRoot, agentType, provider, model, subscriber,
|
|
98
|
+
async function handleEvent(projectRoot, agentType, provider, model, subscriber, nickname, evt, cliSessionState, busSender) {
|
|
73
99
|
if (!evt || !evt.data || !evt.data.message) return;
|
|
74
100
|
const prompt = evt.data.message;
|
|
75
101
|
const publisher = evt.publisher || "unknown";
|
|
102
|
+
const sandbox = "workspace-write";
|
|
103
|
+
const streamState = { emitted: false, lastChar: "" };
|
|
104
|
+
|
|
105
|
+
const emitStreamDelta = (delta) => {
|
|
106
|
+
const text = String(delta || "");
|
|
107
|
+
if (!text) return;
|
|
108
|
+
streamState.emitted = true;
|
|
109
|
+
streamState.lastChar = text.slice(-1);
|
|
110
|
+
busSender.enqueue(publisher, JSON.stringify({ stream: true, delta: text }));
|
|
111
|
+
};
|
|
76
112
|
|
|
77
113
|
let res = await runCliAgent({
|
|
78
114
|
provider,
|
|
79
115
|
model,
|
|
80
116
|
prompt,
|
|
81
117
|
sessionId: cliSessionState.cliSessionId,
|
|
118
|
+
sandbox,
|
|
82
119
|
cwd: projectRoot,
|
|
120
|
+
onStreamDelta: emitStreamDelta,
|
|
83
121
|
});
|
|
84
122
|
|
|
85
123
|
// Handle session errors with immediate retry (only for claude)
|
|
@@ -95,7 +133,9 @@ async function handleEvent(projectRoot, agentType, provider, model, subscriber,
|
|
|
95
133
|
model,
|
|
96
134
|
prompt,
|
|
97
135
|
sessionId: null, // Let runCliAgent generate new session
|
|
136
|
+
sandbox,
|
|
98
137
|
cwd: projectRoot,
|
|
138
|
+
onStreamDelta: emitStreamDelta,
|
|
99
139
|
});
|
|
100
140
|
}
|
|
101
141
|
}
|
|
@@ -113,32 +153,46 @@ async function handleEvent(projectRoot, agentType, provider, model, subscriber,
|
|
|
113
153
|
reply = `[internal:${agentType}] error: ${res.error || "unknown error"}`;
|
|
114
154
|
}
|
|
115
155
|
|
|
156
|
+
if (streamState.emitted) {
|
|
157
|
+
if (!res.ok) {
|
|
158
|
+
if (streamState.lastChar !== "\n") {
|
|
159
|
+
busSender.enqueue(publisher, JSON.stringify({ stream: true, delta: "\n" }));
|
|
160
|
+
}
|
|
161
|
+
busSender.enqueue(publisher, JSON.stringify({ stream: true, delta: reply }));
|
|
162
|
+
}
|
|
163
|
+
busSender.enqueue(
|
|
164
|
+
publisher,
|
|
165
|
+
JSON.stringify({ stream: true, done: true, reason: res.ok ? "complete" : "error" })
|
|
166
|
+
);
|
|
167
|
+
await busSender.flush();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
116
171
|
if (!reply) return;
|
|
117
172
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
env: buildEnv(agentType, sessionId, subscriber, nickname),
|
|
121
|
-
stdio: "ignore",
|
|
122
|
-
});
|
|
173
|
+
busSender.enqueue(publisher, reply);
|
|
174
|
+
await busSender.flush();
|
|
123
175
|
}
|
|
124
176
|
|
|
125
177
|
async function runInternalRunner({ projectRoot, agentType = "codex" }) {
|
|
126
|
-
|
|
178
|
+
// Internal runner 必须由 daemon 启动,UFOO_SUBSCRIBER_ID 应该已经设置
|
|
179
|
+
const { subscriber, agentType: parsedAgentType, sessionId } = parseSubscriberId();
|
|
127
180
|
const nickname = process.env.UFOO_NICKNAME || "";
|
|
128
|
-
const { subscriber } = joinBus(projectRoot, agentType, sessionId, nickname);
|
|
129
|
-
if (!subscriber) {
|
|
130
|
-
throw new Error("Failed to join bus for internal runner");
|
|
131
|
-
}
|
|
132
181
|
|
|
133
|
-
const queueDir = path.join(projectRoot
|
|
182
|
+
const queueDir = path.join(getUfooPaths(projectRoot).busQueuesDir, safeSubscriber(subscriber));
|
|
134
183
|
const queueFile = path.join(queueDir, "pending.jsonl");
|
|
135
|
-
const
|
|
184
|
+
const normalizedAgentType = String(agentType || "").trim().toLowerCase();
|
|
185
|
+
if (normalizedAgentType === "ufoo" || normalizedAgentType === "ucode" || normalizedAgentType === "ufoo-code") {
|
|
186
|
+
throw new Error("ufoo core is not supported by headless internal runner; use internal-pty");
|
|
187
|
+
}
|
|
188
|
+
const provider = normalizedAgentType === "codex" ? "codex-cli" : "claude-cli";
|
|
136
189
|
const model = process.env.UFOO_AGENT_MODEL || "";
|
|
190
|
+
const busSender = createBusSender(projectRoot, subscriber);
|
|
137
191
|
|
|
138
192
|
// Session state management for CLI continuity
|
|
139
193
|
// Use stable path based on nickname (if exists) or agent type, NOT subscriber ID
|
|
140
194
|
const stableKey = nickname || `${agentType}-default`;
|
|
141
|
-
const sessionDir = path.join(projectRoot
|
|
195
|
+
const sessionDir = path.join(getUfooPaths(projectRoot).agentDir, "sessions");
|
|
142
196
|
fs.mkdirSync(sessionDir, { recursive: true });
|
|
143
197
|
const stateFile = path.join(sessionDir, `${stableKey}.json`);
|
|
144
198
|
|
|
@@ -155,6 +209,8 @@ async function runInternalRunner({ projectRoot, agentType = "codex" }) {
|
|
|
155
209
|
|
|
156
210
|
let running = true;
|
|
157
211
|
let processing = false;
|
|
212
|
+
let lastHeartbeat = 0;
|
|
213
|
+
const HEARTBEAT_INTERVAL = 30000; // 30秒心跳间隔
|
|
158
214
|
|
|
159
215
|
const stop = () => {
|
|
160
216
|
running = false;
|
|
@@ -165,11 +221,32 @@ async function runInternalRunner({ projectRoot, agentType = "codex" }) {
|
|
|
165
221
|
|
|
166
222
|
const cliSessionState = { cliSessionId, needsSave: false };
|
|
167
223
|
|
|
224
|
+
// 心跳更新函数
|
|
225
|
+
const updateHeartbeat = () => {
|
|
226
|
+
try {
|
|
227
|
+
spawnSync("ufoo", ["bus", "check", subscriber], {
|
|
228
|
+
cwd: projectRoot,
|
|
229
|
+
env: { ...process.env, UFOO_SUBSCRIBER_ID: subscriber },
|
|
230
|
+
stdio: "ignore",
|
|
231
|
+
timeout: 5000,
|
|
232
|
+
});
|
|
233
|
+
} catch {
|
|
234
|
+
// ignore heartbeat errors
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
168
238
|
while (running) {
|
|
239
|
+
// 定期心跳更新
|
|
240
|
+
const now = Date.now();
|
|
241
|
+
if (now - lastHeartbeat > HEARTBEAT_INTERVAL) {
|
|
242
|
+
updateHeartbeat();
|
|
243
|
+
lastHeartbeat = now;
|
|
244
|
+
}
|
|
245
|
+
|
|
169
246
|
if (!processing) {
|
|
170
247
|
processing = true;
|
|
171
248
|
try {
|
|
172
|
-
const lines =
|
|
249
|
+
const lines = drainQueue(queueFile);
|
|
173
250
|
if (lines.length > 0) {
|
|
174
251
|
const events = [];
|
|
175
252
|
for (const line of lines) {
|
|
@@ -179,11 +256,20 @@ async function runInternalRunner({ projectRoot, agentType = "codex" }) {
|
|
|
179
256
|
// ignore malformed line
|
|
180
257
|
}
|
|
181
258
|
}
|
|
182
|
-
truncateQueue(queueFile);
|
|
183
259
|
|
|
184
260
|
for (const evt of events) {
|
|
185
261
|
// eslint-disable-next-line no-await-in-loop
|
|
186
|
-
await handleEvent(
|
|
262
|
+
await handleEvent(
|
|
263
|
+
projectRoot,
|
|
264
|
+
parsedAgentType,
|
|
265
|
+
provider,
|
|
266
|
+
model,
|
|
267
|
+
subscriber,
|
|
268
|
+
nickname,
|
|
269
|
+
evt,
|
|
270
|
+
cliSessionState,
|
|
271
|
+
busSender
|
|
272
|
+
);
|
|
187
273
|
}
|
|
188
274
|
|
|
189
275
|
// Persist CLI session state after processing (only if changed and for claude)
|
|
@@ -199,6 +285,10 @@ async function runInternalRunner({ projectRoot, agentType = "codex" }) {
|
|
|
199
285
|
// ignore save errors
|
|
200
286
|
}
|
|
201
287
|
}
|
|
288
|
+
|
|
289
|
+
// 处理消息后更新心跳
|
|
290
|
+
updateHeartbeat();
|
|
291
|
+
lastHeartbeat = now;
|
|
202
292
|
}
|
|
203
293
|
} finally {
|
|
204
294
|
processing = false;
|
|
@@ -209,4 +299,8 @@ async function runInternalRunner({ projectRoot, agentType = "codex" }) {
|
|
|
209
299
|
}
|
|
210
300
|
}
|
|
211
301
|
|
|
212
|
-
module.exports = {
|
|
302
|
+
module.exports = {
|
|
303
|
+
runInternalRunner,
|
|
304
|
+
createBusSender,
|
|
305
|
+
handleEvent,
|
|
306
|
+
};
|