shennian 0.2.89 → 0.2.90
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/assets/wechat-channel/macos/manifest.json +13 -4
- package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +548 -0
- package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
- package/dist/src/agent-env.js +4 -105
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude.js +8 -305
- package/dist/src/agents/codex-control.js +2 -188
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.js +15 -916
- package/dist/src/agents/command-spec.js +2 -413
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor.js +1 -249
- package/dist/src/agents/custom.js +4 -271
- package/dist/src/agents/detect.js +1 -56
- package/dist/src/agents/external-channel-instructions.js +10 -94
- package/dist/src/agents/gemini.js +1 -173
- package/dist/src/agents/manager.js +13 -157
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -187
- package/dist/src/agents/model-registry/parsers.js +4 -447
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -78
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -18
- package/dist/src/agents/openclaw.js +2 -275
- package/dist/src/agents/opencode.js +1 -231
- package/dist/src/agents/pi-context.js +12 -217
- package/dist/src/agents/pi.js +14 -723
- package/dist/src/agents/platform-instructions.js +9 -54
- package/dist/src/channels/base.js +1 -3
- package/dist/src/channels/registry.js +1 -30
- package/dist/src/channels/reply-split.js +10 -89
- package/dist/src/channels/runtime.js +5 -564
- package/dist/src/channels/secret-registry.js +1 -46
- package/dist/src/channels/websocket.js +8 -378
- package/dist/src/channels/wechat-channel/anchor.js +1 -65
- package/dist/src/channels/wechat-channel/client.js +1 -96
- package/dist/src/channels/wechat-channel/cooldown.js +1 -38
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -71
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +10 -1
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -68
- package/dist/src/channels/wechat-channel/helper-client.js +3 -149
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +1 -1
- package/dist/src/channels/wechat-channel/helper-protocol.js +1 -115
- package/dist/src/channels/wechat-channel/index.d.ts +1 -0
- package/dist/src/channels/wechat-channel/index.js +1 -19
- package/dist/src/channels/wechat-channel/ledger.js +1 -54
- package/dist/src/channels/wechat-channel/media-resolver.js +1 -181
- package/dist/src/channels/wechat-channel/message-key.js +1 -105
- package/dist/src/channels/wechat-channel/observer.js +1 -118
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +3 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -112
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
- package/dist/src/channels/wechat-channel/preflight.js +1 -48
- package/dist/src/channels/wechat-channel/runner.js +1 -84
- package/dist/src/channels/wechat-channel/runtime.js +1 -66
- package/dist/src/channels/wechat-channel/scheduler.d.ts +5 -0
- package/dist/src/channels/wechat-channel/scheduler.js +1 -152
- package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
- package/dist/src/channels/wechat-rpa/macos.js +6 -48
- package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
- package/dist/src/channels/wechat-rpa.js +6 -1028
- package/dist/src/channels/wecom.js +4 -357
- package/dist/src/commands/agent.js +6 -131
- package/dist/src/commands/daemon-windows.js +8 -48
- package/dist/src/commands/daemon.js +19 -1013
- package/dist/src/commands/external-attachments.js +1 -51
- package/dist/src/commands/external.js +1 -137
- package/dist/src/commands/manager.js +2 -391
- package/dist/src/commands/pair-qr.js +1 -6
- package/dist/src/commands/pair.js +9 -287
- package/dist/src/commands/tools.js +1 -34
- package/dist/src/commands/upgrade.js +1 -198
- package/dist/src/config/index.js +1 -35
- package/dist/src/daemon-log.js +6 -58
- package/dist/src/env-path.js +1 -64
- package/dist/src/fs/boundary.js +1 -126
- package/dist/src/fs/handler.js +1 -130
- package/dist/src/fs/security.js +1 -32
- package/dist/src/fs/text-decoder.js +1 -110
- package/dist/src/index.js +2 -404
- package/dist/src/log-reporter.js +1 -16
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +2 -269
- package/dist/src/manager/runtime.js +19 -1007
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/opencode-parser.js +3 -123
- package/dist/src/native-fusion/parser-common.js +8 -264
- package/dist/src/native-fusion/parsers.js +8 -729
- package/dist/src/native-fusion/service.js +2 -225
- package/dist/src/native-fusion/state.js +1 -22
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/region.js +1 -88
- package/dist/src/relay/client.js +1 -343
- package/dist/src/session/archive-zip.js +1 -220
- package/dist/src/session/handlers/agent-config.js +1 -150
- package/dist/src/session/handlers/agents.js +1 -55
- package/dist/src/session/handlers/chat.js +2 -751
- package/dist/src/session/handlers/control.js +1 -55
- package/dist/src/session/handlers/fs.js +1 -783
- package/dist/src/session/handlers/session-refresh.js +1 -47
- package/dist/src/session/handlers/skills.js +1 -121
- package/dist/src/session/handlers/title.js +1 -60
- package/dist/src/session/handlers/tool-detail.js +1 -218
- package/dist/src/session/manager.js +1 -319
- package/dist/src/session/projection.js +1 -54
- package/dist/src/session/queue.js +4 -317
- package/dist/src/session/remote-attachments.js +1 -72
- package/dist/src/session/store.js +3 -109
- package/dist/src/session/types.js +1 -4
- package/dist/src/skills/registry.js +15 -148
- package/dist/src/skills/setup.js +1 -101
- package/dist/src/tools/markdown-to-pdf.js +10 -346
- package/dist/src/upgrade/engine.js +3 -347
- package/package.json +3 -2
package/dist/src/index.js
CHANGED
|
@@ -1,404 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// @test src/__tests__/daemon-autostart.test.ts
|
|
4
|
-
import { Command } from 'commander';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import os from 'node:os';
|
|
7
|
-
import fs from 'node:fs';
|
|
8
|
-
import { loadConfig, saveConfig, configPath, getShennianDir, resolveShennianPath, } from './config/index.js';
|
|
9
|
-
import { CliRelayClient } from './relay/client.js';
|
|
10
|
-
import { registerPairCommand, runSmartStart } from './commands/pair.js';
|
|
11
|
-
import { clearDaemonPidIfOwner, createDaemonInstanceId, clearDaemonLauncher, findRunningDaemonProcessIds, isRemoteAccessDisabled, registerDaemonCommand, writeDaemonPid, writeDaemonLauncher, } from './commands/daemon.js';
|
|
12
|
-
import { registerAgentCommand } from './commands/agent.js';
|
|
13
|
-
import { registerManagerCommand } from './commands/manager.js';
|
|
14
|
-
import { registerExternalCommand } from './commands/external.js';
|
|
15
|
-
import { registerUpgradeCommand } from './commands/upgrade.js';
|
|
16
|
-
import { registerToolsCommand } from './commands/tools.js';
|
|
17
|
-
import { SessionManager } from './session/manager.js';
|
|
18
|
-
import { SERVERS, regionToUrl, urlToRegion } from './region.js';
|
|
19
|
-
import { getCurrentVersion, handleStartupCrashCheck, checkForUpdate, isUpgradeVersionInCooldown, recordUpgradeFailure, } from './upgrade/engine.js';
|
|
20
|
-
import { detectAgents } from './agents/detect.js';
|
|
21
|
-
import { augmentProcessPath } from './env-path.js';
|
|
22
|
-
augmentProcessPath();
|
|
23
|
-
const cliVersion = getCurrentVersion();
|
|
24
|
-
const AUTO_UPGRADE_INITIAL_DELAY_MS = 30_000;
|
|
25
|
-
const AUTO_UPGRADE_POLL_INTERVAL_MS = 5 * 60_000;
|
|
26
|
-
import { getCachedAgentInfos, resolveAgentInfos } from './agents/model-registry.js';
|
|
27
|
-
import { initCliLogReporter, reportLog } from './log-reporter.js';
|
|
28
|
-
import { isNativeFusionEnabled } from './native-fusion/config.js';
|
|
29
|
-
import { NativeSessionFusionService } from './native-fusion/service.js';
|
|
30
|
-
import { startDaemonLogRetention } from './daemon-log.js';
|
|
31
|
-
const SHENNIAN_DIR = getShennianDir();
|
|
32
|
-
const PID_FILE = resolveShennianPath('daemon.pid');
|
|
33
|
-
function readDaemonPidFile() {
|
|
34
|
-
try {
|
|
35
|
-
const raw = fs.readFileSync(PID_FILE, 'utf-8').trim();
|
|
36
|
-
if (raw.startsWith('{')) {
|
|
37
|
-
const parsed = JSON.parse(raw);
|
|
38
|
-
const pid = Number(parsed.pid);
|
|
39
|
-
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
40
|
-
}
|
|
41
|
-
const pid = parseInt(raw, 10);
|
|
42
|
-
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function httpToWs(url) {
|
|
49
|
-
return url.replace(/^https:\/\//, 'wss://').replace(/^http:\/\//, 'ws://');
|
|
50
|
-
}
|
|
51
|
-
function formatDisconnectInfo(info) {
|
|
52
|
-
const parts = [
|
|
53
|
-
`trigger=${info.trigger ?? 'unknown'}`,
|
|
54
|
-
`phase=${info.phase}`,
|
|
55
|
-
`code=${info.code ?? 'unknown'}`,
|
|
56
|
-
`attempt=${info.reconnectAttempt}`,
|
|
57
|
-
];
|
|
58
|
-
if (info.reason)
|
|
59
|
-
parts.push(`reason=${info.reason}`);
|
|
60
|
-
if (info.error)
|
|
61
|
-
parts.push(`error=${info.error}`);
|
|
62
|
-
return parts.join(' ');
|
|
63
|
-
}
|
|
64
|
-
async function waitForPidExit(pid, timeoutMs = 5000) {
|
|
65
|
-
const startedAt = Date.now();
|
|
66
|
-
while (Date.now() - startedAt < timeoutMs) {
|
|
67
|
-
try {
|
|
68
|
-
process.kill(pid, 0);
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
process.kill(pid, 0);
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
const program = new Command();
|
|
84
|
-
program.name('shennian').description('Shennian — AI Agent Control Plane').version(cliVersion);
|
|
85
|
-
program
|
|
86
|
-
.option('--api <url>', 'Server URL override')
|
|
87
|
-
.option('--name <name>', 'Machine name', os.hostname())
|
|
88
|
-
.action(async (opts) => {
|
|
89
|
-
const config = loadConfig();
|
|
90
|
-
const serverUrl = opts.api ?? process.env.SHENNIAN_DESKTOP_SERVER_URL ?? config.serverUrl ?? undefined;
|
|
91
|
-
await runSmartStart(serverUrl, opts.name);
|
|
92
|
-
});
|
|
93
|
-
// run-service: internal command used by the background service process
|
|
94
|
-
program
|
|
95
|
-
.command('run-service', { hidden: true })
|
|
96
|
-
.description('(internal) Connect to relay server, called by the background service')
|
|
97
|
-
.option('--api <url>', 'Server URL override')
|
|
98
|
-
.action(async (opts) => {
|
|
99
|
-
const envFile = resolveShennianPath('env.json');
|
|
100
|
-
try {
|
|
101
|
-
const saved = JSON.parse(fs.readFileSync(envFile, 'utf-8'));
|
|
102
|
-
for (const [k, v] of Object.entries(saved)) {
|
|
103
|
-
if (!process.env[k])
|
|
104
|
-
process.env[k] = v;
|
|
105
|
-
}
|
|
106
|
-
augmentProcessPath();
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
// env.json may not exist yet
|
|
110
|
-
}
|
|
111
|
-
const logRetentionTimer = startDaemonLogRetention();
|
|
112
|
-
if (isRemoteAccessDisabled()) {
|
|
113
|
-
console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`);
|
|
114
|
-
clearInterval(logRetentionTimer);
|
|
115
|
-
process.exit(0);
|
|
116
|
-
}
|
|
117
|
-
// Single-instance guard. Service-manager starts are authoritative and may
|
|
118
|
-
// need to take over from an older detached process after app/daemon upgrades.
|
|
119
|
-
const serviceManagedStart = Boolean(process.env.INVOCATION_ID ||
|
|
120
|
-
process.env.JOURNAL_STREAM ||
|
|
121
|
-
process.env.SHENNIAN_DESKTOP_SERVER_URL);
|
|
122
|
-
const stopExistingDaemon = async (oldPid, reason) => {
|
|
123
|
-
console.log(`[${new Date().toISOString()}] ${reason} (PID ${oldPid})`);
|
|
124
|
-
process.kill(oldPid, 'SIGTERM');
|
|
125
|
-
const stopped = await waitForPidExit(oldPid);
|
|
126
|
-
if (!stopped) {
|
|
127
|
-
process.kill(oldPid, 'SIGKILL');
|
|
128
|
-
await waitForPidExit(oldPid, 2000);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
try {
|
|
132
|
-
const oldPid = readDaemonPidFile();
|
|
133
|
-
if (oldPid && oldPid !== process.pid) {
|
|
134
|
-
try {
|
|
135
|
-
process.kill(oldPid, 0);
|
|
136
|
-
if (serviceManagedStart) {
|
|
137
|
-
await stopExistingDaemon(oldPid, 'managed start taking over from existing daemon');
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
console.log(`[${new Date().toISOString()}] daemon already running (PID ${oldPid}), skipping duplicate start`);
|
|
141
|
-
process.exit(0);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
// Stale pid; continue booting and overwrite it below.
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
/* noop */
|
|
151
|
-
}
|
|
152
|
-
const orphanPids = findRunningDaemonProcessIds(process.pid);
|
|
153
|
-
if (orphanPids.length > 0) {
|
|
154
|
-
if (serviceManagedStart) {
|
|
155
|
-
for (const orphanPid of orphanPids) {
|
|
156
|
-
try {
|
|
157
|
-
await stopExistingDaemon(orphanPid, 'managed start taking over from orphan daemon');
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
// Keep booting; the normal pid-file guard below still protects the managed daemon.
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
console.log(`[${new Date().toISOString()}] daemon already running (PID ${orphanPids[0]}), skipping duplicate start`);
|
|
166
|
-
process.exit(0);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const daemonInstanceId = createDaemonInstanceId();
|
|
170
|
-
writeDaemonPid(process.pid, daemonInstanceId, { version: cliVersion });
|
|
171
|
-
writeDaemonLauncher(process.pid, undefined, daemonInstanceId);
|
|
172
|
-
process.on('exit', () => {
|
|
173
|
-
clearDaemonPidIfOwner(process.pid, daemonInstanceId);
|
|
174
|
-
clearDaemonLauncher(daemonInstanceId);
|
|
175
|
-
});
|
|
176
|
-
// Crash detection: if we're recovering from a failed upgrade, rollback and exit
|
|
177
|
-
const didRollback = await handleStartupCrashCheck();
|
|
178
|
-
if (didRollback) {
|
|
179
|
-
console.log(`[${new Date().toISOString()}] Rolled back to previous version, restarting...`);
|
|
180
|
-
process.exit(0);
|
|
181
|
-
}
|
|
182
|
-
const config = loadConfig();
|
|
183
|
-
if (!config.machineToken) {
|
|
184
|
-
console.error(chalk.red('✗ Not paired yet. Run: shennian'));
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
const serverUrl = opts.api ?? process.env.SHENNIAN_DESKTOP_SERVER_URL ?? config.serverUrl ?? SERVERS.cn.url;
|
|
188
|
-
const wsBase = httpToWs(serverUrl);
|
|
189
|
-
const wsUrl = `${wsBase}/relay/machine`;
|
|
190
|
-
const currentCliVersion = getCurrentVersion();
|
|
191
|
-
const detectedAgents = detectAgents();
|
|
192
|
-
const agentList = detectedAgents.map((a) => a.type);
|
|
193
|
-
const cachedAgentInfos = getCachedAgentInfos(detectedAgents);
|
|
194
|
-
if (config.machineId) {
|
|
195
|
-
initCliLogReporter(serverUrl, config.machineId);
|
|
196
|
-
}
|
|
197
|
-
console.log(`[${new Date().toISOString()}] Connecting to ${wsUrl}... (v${currentCliVersion}) agents: ${agentList.join(',')}`);
|
|
198
|
-
reportLog({
|
|
199
|
-
level: 'info',
|
|
200
|
-
wsEvent: 'daemon.start',
|
|
201
|
-
metadata: { version: currentCliVersion, agents: agentList },
|
|
202
|
-
});
|
|
203
|
-
let nativeFusion = null;
|
|
204
|
-
const client = new CliRelayClient({
|
|
205
|
-
serverUrl: wsUrl,
|
|
206
|
-
machineToken: config.machineToken,
|
|
207
|
-
cliVersion: currentCliVersion,
|
|
208
|
-
agentList,
|
|
209
|
-
onConnected: () => {
|
|
210
|
-
console.log(`[${new Date().toISOString()}] ✓ Connected`);
|
|
211
|
-
reportLog({ level: 'info', wsEvent: 'daemon.connected' });
|
|
212
|
-
if (cachedAgentInfos.some((agent) => agent.models.length > 0)) {
|
|
213
|
-
client.sendEvent({
|
|
214
|
-
type: 'event',
|
|
215
|
-
event: 'machine.agents',
|
|
216
|
-
payload: {
|
|
217
|
-
agentList,
|
|
218
|
-
agents: cachedAgentInfos,
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
void resolveAgentInfos(detectedAgents, {
|
|
223
|
-
serverUrl: config.serverUrl ?? serverUrl,
|
|
224
|
-
authToken: config.machineToken ?? config.accessToken,
|
|
225
|
-
})
|
|
226
|
-
.then((agents) => {
|
|
227
|
-
if (JSON.stringify(agents) === JSON.stringify(cachedAgentInfos))
|
|
228
|
-
return;
|
|
229
|
-
client.sendEvent({
|
|
230
|
-
type: 'event',
|
|
231
|
-
event: 'machine.agents',
|
|
232
|
-
payload: {
|
|
233
|
-
agentList,
|
|
234
|
-
agents,
|
|
235
|
-
},
|
|
236
|
-
});
|
|
237
|
-
})
|
|
238
|
-
.catch(() => { });
|
|
239
|
-
import('./upgrade/engine.js')
|
|
240
|
-
.then(({ readUpgradeAttempt, clearUpgradeAttempt }) => {
|
|
241
|
-
const attempt = readUpgradeAttempt();
|
|
242
|
-
clearUpgradeAttempt();
|
|
243
|
-
if (attempt) {
|
|
244
|
-
console.log(`[${new Date().toISOString()}] [upgrade] Reporting success: ${attempt.from} → ${attempt.to}`);
|
|
245
|
-
client.sendEvent({
|
|
246
|
-
type: 'event',
|
|
247
|
-
event: 'upgrade',
|
|
248
|
-
payload: {
|
|
249
|
-
state: 'success',
|
|
250
|
-
machineId: 'self',
|
|
251
|
-
from: attempt.from,
|
|
252
|
-
to: attempt.to,
|
|
253
|
-
},
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
})
|
|
257
|
-
.catch(() => { });
|
|
258
|
-
void scheduleAutoUpgrade(client, config.autoUpgrade ?? 'patch', currentCliVersion);
|
|
259
|
-
nativeFusion?.handleConnected();
|
|
260
|
-
},
|
|
261
|
-
onDisconnected: (info) => {
|
|
262
|
-
console.log(`[${new Date().toISOString()}] ⚠ Disconnected, reconnecting... ${formatDisconnectInfo(info)}`);
|
|
263
|
-
reportLog({
|
|
264
|
-
level: 'warn',
|
|
265
|
-
wsEvent: 'daemon.disconnected',
|
|
266
|
-
metadata: {
|
|
267
|
-
code: info.code,
|
|
268
|
-
reason: info.reason,
|
|
269
|
-
error: info.error,
|
|
270
|
-
phase: info.phase,
|
|
271
|
-
trigger: info.trigger,
|
|
272
|
-
reconnectAttempt: info.reconnectAttempt,
|
|
273
|
-
},
|
|
274
|
-
});
|
|
275
|
-
},
|
|
276
|
-
onReq: (req) => {
|
|
277
|
-
console.log(`[${new Date().toISOString()}] [req] ${req.method}`);
|
|
278
|
-
reportLog({
|
|
279
|
-
level: 'info',
|
|
280
|
-
type: 'ws',
|
|
281
|
-
wsEvent: req.method,
|
|
282
|
-
wsDirection: 'in',
|
|
283
|
-
traceId: req.traceId,
|
|
284
|
-
});
|
|
285
|
-
void sessionManager.handleReq(req);
|
|
286
|
-
},
|
|
287
|
-
});
|
|
288
|
-
nativeFusion =
|
|
289
|
-
isNativeFusionEnabled()
|
|
290
|
-
? new NativeSessionFusionService(client)
|
|
291
|
-
: null;
|
|
292
|
-
const sessionManager = new SessionManager(client, nativeFusion, currentCliVersion);
|
|
293
|
-
fs.mkdirSync(SHENNIAN_DIR, { recursive: true });
|
|
294
|
-
writeDaemonPid(process.pid, daemonInstanceId, { version: currentCliVersion });
|
|
295
|
-
writeDaemonLauncher(process.pid, undefined, daemonInstanceId);
|
|
296
|
-
client.connect();
|
|
297
|
-
process.stdin.resume();
|
|
298
|
-
const shutdown = () => {
|
|
299
|
-
console.log(chalk.gray('\nDisconnecting...'));
|
|
300
|
-
reportLog({ level: 'info', wsEvent: 'daemon.stop' });
|
|
301
|
-
clearInterval(logRetentionTimer);
|
|
302
|
-
sessionManager.cleanup();
|
|
303
|
-
nativeFusion?.stop();
|
|
304
|
-
client.disconnect();
|
|
305
|
-
clearDaemonPidIfOwner(process.pid, daemonInstanceId);
|
|
306
|
-
clearDaemonLauncher(daemonInstanceId);
|
|
307
|
-
process.exit(0);
|
|
308
|
-
};
|
|
309
|
-
process.on('SIGINT', shutdown);
|
|
310
|
-
process.on('SIGTERM', shutdown);
|
|
311
|
-
});
|
|
312
|
-
// config: view and modify settings
|
|
313
|
-
const configCmd = program.command('config').description('View or modify configuration');
|
|
314
|
-
configCmd
|
|
315
|
-
.command('show', { isDefault: true })
|
|
316
|
-
.description('Show current configuration')
|
|
317
|
-
.action(() => {
|
|
318
|
-
console.log(`Config file: ${configPath}`);
|
|
319
|
-
const config = loadConfig();
|
|
320
|
-
const display = { ...config };
|
|
321
|
-
if (display.machineToken)
|
|
322
|
-
display.machineToken = display.machineToken.slice(0, 12) + '...';
|
|
323
|
-
if (display.serverUrl) {
|
|
324
|
-
const region = urlToRegion(display.serverUrl);
|
|
325
|
-
console.log(`Region: ${region} (${SERVERS[region].label})`);
|
|
326
|
-
}
|
|
327
|
-
console.log(JSON.stringify(display, null, 2));
|
|
328
|
-
});
|
|
329
|
-
configCmd
|
|
330
|
-
.command('set')
|
|
331
|
-
.description('Update a config value')
|
|
332
|
-
.argument('<key>', 'Config key (e.g. "server")')
|
|
333
|
-
.argument('<value>', 'Config value (e.g. "cn" or "global")')
|
|
334
|
-
.action((key, value) => {
|
|
335
|
-
const config = loadConfig();
|
|
336
|
-
if (key === 'server') {
|
|
337
|
-
if (value !== 'cn' && value !== 'global') {
|
|
338
|
-
console.error(chalk.red('✗ Value must be "cn" or "global"'));
|
|
339
|
-
process.exit(1);
|
|
340
|
-
}
|
|
341
|
-
const region = value;
|
|
342
|
-
config.serverUrl = regionToUrl(region);
|
|
343
|
-
saveConfig(config);
|
|
344
|
-
console.log(chalk.green(`✓ Server set to ${SERVERS[region].label}`));
|
|
345
|
-
console.log(chalk.yellow(' Restart the background service for this to take effect: shennian stop && shennian start'));
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
console.error(chalk.red(`✗ Unknown config key: ${key}. Supported: server`));
|
|
349
|
-
process.exit(1);
|
|
350
|
-
});
|
|
351
|
-
registerPairCommand(program);
|
|
352
|
-
registerDaemonCommand(program);
|
|
353
|
-
registerAgentCommand(program);
|
|
354
|
-
registerManagerCommand(program);
|
|
355
|
-
registerExternalCommand(program);
|
|
356
|
-
registerUpgradeCommand(program);
|
|
357
|
-
registerToolsCommand(program);
|
|
358
|
-
program.parse();
|
|
359
|
-
// ─── Auto-upgrade helper ──────────────────────────────────────────────────────
|
|
360
|
-
async function scheduleAutoUpgrade(client, policy, currentVersion) {
|
|
361
|
-
if (policy === 'none')
|
|
362
|
-
return;
|
|
363
|
-
let upgradeInFlight = false;
|
|
364
|
-
const tick = async () => {
|
|
365
|
-
if (upgradeInFlight)
|
|
366
|
-
return;
|
|
367
|
-
let result;
|
|
368
|
-
try {
|
|
369
|
-
result = await checkForUpdate(currentVersion);
|
|
370
|
-
}
|
|
371
|
-
catch {
|
|
372
|
-
return; // silently skip on network error
|
|
373
|
-
}
|
|
374
|
-
if (!result.hasUpdate)
|
|
375
|
-
return;
|
|
376
|
-
const { changeType, current, latest } = result;
|
|
377
|
-
// Respect the policy
|
|
378
|
-
if (policy === 'patch' && changeType !== 'patch')
|
|
379
|
-
return;
|
|
380
|
-
if (policy === 'minor' && changeType === 'major')
|
|
381
|
-
return;
|
|
382
|
-
if (isUpgradeVersionInCooldown(latest))
|
|
383
|
-
return;
|
|
384
|
-
console.log(`[${new Date().toISOString()}] [upgrade] ${current} → ${latest} (${changeType}), auto-upgrading...`);
|
|
385
|
-
upgradeInFlight = true;
|
|
386
|
-
try {
|
|
387
|
-
const { handleUpgradeStart } = await import('./commands/upgrade.js');
|
|
388
|
-
// Use a dummy reqId since this is self-triggered
|
|
389
|
-
await handleUpgradeStart(client, 'auto-upgrade', latest, { currentVersion });
|
|
390
|
-
}
|
|
391
|
-
catch (err) {
|
|
392
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
393
|
-
const failure = recordUpgradeFailure(latest, message);
|
|
394
|
-
console.log(`[${new Date().toISOString()}] [upgrade] ${latest} failed, retry after ${new Date(failure.nextRetryAt).toISOString()}: ${message}`);
|
|
395
|
-
}
|
|
396
|
-
finally {
|
|
397
|
-
upgradeInFlight = false;
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
// Delay slightly so we don't hit npm on every cold start during development,
|
|
401
|
-
// then keep polling so a bad published patch can be superseded by a good one.
|
|
402
|
-
setTimeout(() => void tick(), AUTO_UPGRADE_INITIAL_DELAY_MS);
|
|
403
|
-
setInterval(() => void tick(), AUTO_UPGRADE_POLL_INTERVAL_MS);
|
|
404
|
-
}
|
|
1
|
+
import{Command as V}from"commander";import u from"chalk";import M from"node:os";import R from"node:fs";import{loadConfig as w,saveConfig as G,configPath as J,getShennianDir as j,resolveShennianPath as A}from"./config/index.js";import{CliRelayClient as H}from"./relay/client.js";import{registerPairCommand as K,runSmartStart as B}from"./commands/pair.js";import{clearDaemonPidIfOwner as N,createDaemonInstanceId as W,clearDaemonLauncher as O,findRunningDaemonProcessIds as Y,isRemoteAccessDisabled as q,registerDaemonCommand as z,writeDaemonPid as T,writeDaemonLauncher as _}from"./commands/daemon.js";import{registerAgentCommand as Q}from"./commands/agent.js";import{registerManagerCommand as X}from"./commands/manager.js";import{registerExternalCommand as Z}from"./commands/external.js";import{registerUpgradeCommand as ee}from"./commands/upgrade.js";import{registerToolsCommand as ne}from"./commands/tools.js";import{SessionManager as oe}from"./session/manager.js";import{SERVERS as k,regionToUrl as te,urlToRegion as re}from"./region.js";import{getCurrentVersion as P,handleStartupCrashCheck as se,checkForUpdate as ae,isUpgradeVersionInCooldown as ie,recordUpgradeFailure as ce}from"./upgrade/engine.js";import{detectAgents as le}from"./agents/detect.js";import{augmentProcessPath as L}from"./env-path.js";L();const b=P(),pe=3e4,de=5*6e4;import{getCachedAgentInfos as me,resolveAgentInfos as ge}from"./agents/model-registry.js";import{initCliLogReporter as ue,reportLog as v}from"./log-reporter.js";import{isNativeFusionEnabled as fe}from"./native-fusion/config.js";import{NativeSessionFusionService as he}from"./native-fusion/service.js";import{startDaemonLogRetention as ve}from"./daemon-log.js";const Se=j(),Ie=A("daemon.pid");function we(){try{const n=R.readFileSync(Ie,"utf-8").trim();if(n.startsWith("{")){const t=JSON.parse(n),r=Number(t.pid);return Number.isInteger(r)&&r>0?r:null}const o=parseInt(n,10);return Number.isInteger(o)&&o>0?o:null}catch{return null}}function De(n){return n.replace(/^https:\/\//,"wss://").replace(/^http:\/\//,"ws://")}function ye(n){const o=[`trigger=${n.trigger??"unknown"}`,`phase=${n.phase}`,`code=${n.code??"unknown"}`,`attempt=${n.reconnectAttempt}`];return n.reason&&o.push(`reason=${n.reason}`),n.error&&o.push(`error=${n.error}`),o.join(" ")}async function x(n,o=5e3){const t=Date.now();for(;Date.now()-t<o;){try{process.kill(n,0)}catch{return!0}await new Promise(r=>setTimeout(r,100))}try{return process.kill(n,0),!1}catch{return!0}}const i=new V;i.name("shennian").description("Shennian \u2014 AI Agent Control Plane").version(b),i.option("--api <url>","Server URL override").option("--name <name>","Machine name",M.hostname()).action(async n=>{const o=w(),t=n.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??o.serverUrl??void 0;await B(t,n.name)}),i.command("run-service",{hidden:!0}).description("(internal) Connect to relay server, called by the background service").option("--api <url>","Server URL override").action(async n=>{const o=A("env.json");try{const e=JSON.parse(R.readFileSync(o,"utf-8"));for(const[g,p]of Object.entries(e))process.env[g]||(process.env[g]=p);L()}catch{}const t=ve();q()&&(console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`),clearInterval(t),process.exit(0));const r=!!(process.env.INVOCATION_ID||process.env.JOURNAL_STREAM||process.env.SHENNIAN_DESKTOP_SERVER_URL),f=async(e,g)=>{console.log(`[${new Date().toISOString()}] ${g} (PID ${e})`),process.kill(e,"SIGTERM"),await x(e)||(process.kill(e,"SIGKILL"),await x(e,2e3))};try{const e=we();if(e&&e!==process.pid)try{process.kill(e,0),r?await f(e,"managed start taking over from existing daemon"):(console.log(`[${new Date().toISOString()}] daemon already running (PID ${e}), skipping duplicate start`),process.exit(0))}catch{}}catch{}const d=Y(process.pid);if(d.length>0)if(r)for(const e of d)try{await f(e,"managed start taking over from orphan daemon")}catch{}else console.log(`[${new Date().toISOString()}] daemon already running (PID ${d[0]}), skipping duplicate start`),process.exit(0);const a=W();T(process.pid,a,{version:b}),_(process.pid,void 0,a),process.on("exit",()=>{N(process.pid,a),O(a)}),await se()&&(console.log(`[${new Date().toISOString()}] Rolled back to previous version, restarting...`),process.exit(0));const s=w();s.machineToken||(console.error(u.red("\u2717 Not paired yet. Run: shennian")),process.exit(1));const c=n.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??s.serverUrl??k.cn.url,S=`${De(c)}/relay/machine`,m=P(),y=le(),h=y.map(e=>e.type),$=me(y);s.machineId&&ue(c,s.machineId),console.log(`[${new Date().toISOString()}] Connecting to ${S}... (v${m}) agents: ${h.join(",")}`),v({level:"info",wsEvent:"daemon.start",metadata:{version:m,agents:h}});let I=null;const l=new H({serverUrl:S,machineToken:s.machineToken,cliVersion:m,agentList:h,onConnected:()=>{console.log(`[${new Date().toISOString()}] \u2713 Connected`),v({level:"info",wsEvent:"daemon.connected"}),$.some(e=>e.models.length>0)&&l.sendEvent({type:"event",event:"machine.agents",payload:{agentList:h,agents:$}}),ge(y,{serverUrl:s.serverUrl??c,authToken:s.machineToken??s.accessToken}).then(e=>{JSON.stringify(e)!==JSON.stringify($)&&l.sendEvent({type:"event",event:"machine.agents",payload:{agentList:h,agents:e}})}).catch(()=>{}),import("./upgrade/engine.js").then(({readUpgradeAttempt:e,clearUpgradeAttempt:g})=>{const p=e();g(),p&&(console.log(`[${new Date().toISOString()}] [upgrade] Reporting success: ${p.from} \u2192 ${p.to}`),l.sendEvent({type:"event",event:"upgrade",payload:{state:"success",machineId:"self",from:p.from,to:p.to}}))}).catch(()=>{}),$e(l,s.autoUpgrade??"patch",m),I?.handleConnected()},onDisconnected:e=>{console.log(`[${new Date().toISOString()}] \u26A0 Disconnected, reconnecting... ${ye(e)}`),v({level:"warn",wsEvent:"daemon.disconnected",metadata:{code:e.code,reason:e.reason,error:e.error,phase:e.phase,trigger:e.trigger,reconnectAttempt:e.reconnectAttempt}})},onReq:e=>{console.log(`[${new Date().toISOString()}] [req] ${e.method}`),v({level:"info",type:"ws",wsEvent:e.method,wsDirection:"in",traceId:e.traceId}),U.handleReq(e)}});I=fe()?new he(l):null;const U=new oe(l,I,m);R.mkdirSync(Se,{recursive:!0}),T(process.pid,a,{version:m}),_(process.pid,void 0,a),l.connect(),process.stdin.resume();const C=()=>{console.log(u.gray(`
|
|
2
|
+
Disconnecting...`)),v({level:"info",wsEvent:"daemon.stop"}),clearInterval(t),U.cleanup(),I?.stop(),l.disconnect(),N(process.pid,a),O(a),process.exit(0)};process.on("SIGINT",C),process.on("SIGTERM",C)});const F=i.command("config").description("View or modify configuration");F.command("show",{isDefault:!0}).description("Show current configuration").action(()=>{console.log(`Config file: ${J}`);const o={...w()};if(o.machineToken&&(o.machineToken=o.machineToken.slice(0,12)+"..."),o.serverUrl){const t=re(o.serverUrl);console.log(`Region: ${t} (${k[t].label})`)}console.log(JSON.stringify(o,null,2))}),F.command("set").description("Update a config value").argument("<key>",'Config key (e.g. "server")').argument("<value>",'Config value (e.g. "cn" or "global")').action((n,o)=>{const t=w();if(n==="server"){o!=="cn"&&o!=="global"&&(console.error(u.red('\u2717 Value must be "cn" or "global"')),process.exit(1));const r=o;t.serverUrl=te(r),G(t),console.log(u.green(`\u2713 Server set to ${k[r].label}`)),console.log(u.yellow(" Restart the background service for this to take effect: shennian stop && shennian start"));return}console.error(u.red(`\u2717 Unknown config key: ${n}. Supported: server`)),process.exit(1)}),K(i),z(i),Q(i),X(i),Z(i),ee(i),ne(i),i.parse();async function $e(n,o,t){if(o==="none")return;let r=!1;const f=async()=>{if(r)return;let d;try{d=await ae(t)}catch{return}if(!d.hasUpdate)return;const{changeType:a,current:E,latest:s}=d;if(!(o==="patch"&&a!=="patch")&&!(o==="minor"&&a==="major")&&!ie(s)){console.log(`[${new Date().toISOString()}] [upgrade] ${E} \u2192 ${s} (${a}), auto-upgrading...`),r=!0;try{const{handleUpgradeStart:c}=await import("./commands/upgrade.js");await c(n,"auto-upgrade",s,{currentVersion:t})}catch(c){const D=c instanceof Error?c.message:String(c),S=ce(s,D);console.log(`[${new Date().toISOString()}] [upgrade] ${s} failed, retry after ${new Date(S.nextRetryAt).toISOString()}: ${D}`)}finally{r=!1}}};setTimeout(()=>{f()},pe),setInterval(()=>{f()},de)}
|
package/dist/src/log-reporter.js
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
let _serverUrl;
|
|
3
|
-
let _machineId;
|
|
4
|
-
export function initCliLogReporter(serverUrl, machineId) {
|
|
5
|
-
_serverUrl = serverUrl.replace(/\/$/, '');
|
|
6
|
-
_machineId = machineId;
|
|
7
|
-
}
|
|
8
|
-
export function generateTraceId() {
|
|
9
|
-
return crypto.randomBytes(8).toString('hex');
|
|
10
|
-
}
|
|
11
|
-
export function reportLog(entry) {
|
|
12
|
-
if (!_serverUrl || !_machineId)
|
|
13
|
-
return;
|
|
14
|
-
// Remote DB log reporting is intentionally disabled; keep the API for callers.
|
|
15
|
-
void entry;
|
|
16
|
-
}
|
|
1
|
+
import n from"node:crypto";let e,t;function p(r,o){e=r.replace(/\/$/,""),t=o}function c(){return n.randomBytes(8).toString("hex")}function a(r){}export{c as generateTraceId,p as initCliLogReporter,a as reportLog};
|
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/manager-runtime.test.ts
|
|
3
|
-
export const MANAGER_SYSTEM_PROMPT = `你是项目经理,是当前项目的管理者。
|
|
1
|
+
const s=`\u4F60\u662F\u9879\u76EE\u7ECF\u7406\uFF0C\u662F\u5F53\u524D\u9879\u76EE\u7684\u7BA1\u7406\u8005\u3002
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
3
|
+
\u4F60\u7684\u804C\u8D23\uFF1A
|
|
4
|
+
- \u7406\u89E3\u7528\u6237\u76EE\u6807\u3002
|
|
5
|
+
- \u62C6\u89E3\u4EFB\u52A1\u3002
|
|
6
|
+
- \u521B\u5EFA\u3001\u6307\u6D3E\u3001\u89C2\u5BDF\u548C\u505C\u6B62\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u4E0B\u7684 worker Agent session\u3002
|
|
7
|
+
- \u6C47\u603B worker \u7ED3\u679C\u3002
|
|
8
|
+
- \u5224\u65AD\u662F\u5426\u9700\u8981\u7EE7\u7EED\u7B49\u5F85\u3001\u8C03\u6574\u5B89\u6392\u3001\u8BE2\u95EE\u7528\u6237\u6216\u9A8C\u6536\u3002
|
|
9
|
+
- \u5728\u9879\u76EE .shennian/ \u76EE\u5F55\u4E0B\u7EF4\u62A4\u5FC5\u8981\u7684\u8BA1\u5212\u3001\u8BB0\u5F55\u548C\u9879\u76EE\u8BB0\u5FC6\u3002
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- sessions read
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
11
|
+
\u4F60\u7684\u8FB9\u754C\uFF1A
|
|
12
|
+
- \u4E0D\u8981\u628A\u81EA\u5DF1\u5F53\u4F5C\u4E3B\u8981\u6267\u884C\u8005\u3002
|
|
13
|
+
- \u4E0D\u8981\u76F4\u63A5\u7F16\u8F91\u4E1A\u52A1\u4EE3\u7801\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u4EB2\u81EA\u6267\u884C\u3002
|
|
14
|
+
- \u53EF\u4EE5\u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u9879\u76EE\u548C\u68C0\u67E5\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u4FBF\u505A\u5224\u65AD\u3002
|
|
15
|
+
- \u9700\u8981\u4FEE\u6539\u4EE3\u7801\u3001\u8FD0\u884C\u6D4B\u8BD5\u3001\u8C03\u7814\u65B9\u6848\u65F6\uFF0C\u4F18\u5148\u521B\u5EFA\u6216\u6307\u6D3E worker\u3002
|
|
16
|
+
- \u6BCF\u6B21\u6536\u5230\u65B0\u4EFB\u52A1\u3001\u8865\u5145\u8981\u6C42\u3001\u7EA0\u504F\u6216\u5916\u90E8\u6D88\u606F\u65F6\uFF0C\u5148\u7528 sessions list \u67E5\u770B\u5F53\u524D\u540C\u9879\u76EE worker\uFF1B\u5982\u679C\u53EF\u80FD\u76F8\u5173\uFF0C\u518D\u7528 sessions read \u8BFB\u53D6\u5FC5\u8981\u6458\u8981\u540E\u5224\u65AD\u662F\u5426\u590D\u7528\u3002
|
|
17
|
+
- \u5982\u679C\u5DF2\u6709 worker \u6B63\u5728\u5904\u7406\u540C\u4E00\u76EE\u6807\u3001\u540C\u4E00\u529F\u80FD\u533A\u3001\u540C\u4E00\u6587\u4EF6\u8303\u56F4\u6216\u540C\u4E00\u95EE\u9898\u94FE\u8DEF\uFF0C\u4F18\u5148\u7528 sessions send \u628A\u65B0\u8981\u6C42\u53D1\u7ED9\u8FD9\u4E2A worker\uFF1B\u5373\u4F7F worker \u6B63\u5FD9\u4E5F\u53EF\u4EE5\u53D1\u9001\uFF0C\u9ED8\u8BA4\u4F1A\u8FDB\u5165\u672C\u673A\u961F\u5217\uFF0C\u4E0D\u8981\u56E0\u4E3A\u5B83\u5FD9\u5C31\u65B0\u5EFA worker\u3002
|
|
18
|
+
- \u53EA\u6709\u6CA1\u6709\u76F8\u5173 worker\u3001\u73B0\u6709 worker \u5DF2\u660E\u663E\u4E0D\u9002\u5408\u7EE7\u7EED\u63A8\u8FDB\u3001\u6216\u4EFB\u52A1\u9700\u8981\u5E76\u884C\u62C6\u5206\u7ED9\u4E0D\u540C\u4E13\u957F\u65F6\uFF0C\u624D\u521B\u5EFA\u65B0\u7684 worker\u3002
|
|
19
|
+
- \u521B\u5EFA\u6216\u6307\u6D3E worker \u540E\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u5F53\u573A\u7EE7\u7EED\u8C03\u5EA6\uFF0C\u5426\u5219\u56DE\u590D\u7528\u6237\u5DF2\u5B89\u6392\u5E76\u7ED3\u675F\u5F53\u524D turn\uFF1B\u4E0D\u8981\u4E3B\u52A8\u8F6E\u8BE2 worker \u72B6\u6001\uFF0C\u795E\u5FF5\u4F1A\u5728 worker \u7EC8\u6001\u6216\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u91CD\u65B0\u5524\u9192\u4F60\u3002
|
|
20
|
+
- sessions read \u8FD4\u56DE\u7684\u662F\u7ED9\u7BA1\u7406\u8005\u770B\u7684\u7B80\u6D01\u8FDB\u5C55\u3001\u5DE5\u5177\u6458\u8981\u548C\u6700\u7EC8\u7ED3\u679C\uFF0C\u4E0D\u662F\u539F\u59CB\u6D41\u5F0F token\uFF1B\u4E0D\u8981\u8981\u6C42\u8BFB\u53D6\u6216\u8F6C\u8FF0\u5B8C\u6574\u6D41\u5F0F\u65E5\u5FD7\u3002
|
|
21
|
+
- \u53EA\u80FD\u7BA1\u7406\u4E0E\u4F60\u5904\u4E8E\u540C\u4E00\u53F0\u673A\u5668\u3001\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u7684\u4F1A\u8BDD\uFF1B\u4E0D\u8981\u8DE8\u673A\u5668\u6216\u8DE8\u9879\u76EE\u8C03\u5EA6\u3002
|
|
22
|
+
- \u4E0D\u8981\u65E0\u9650\u5FAA\u73AF\uFF1B\u6CA1\u6709\u660E\u786E\u4E0B\u4E00\u6B65\u65F6\u8BE2\u95EE\u7528\u6237\u6216\u7ED3\u675F\u5F53\u524D turn \u7B49\u5F85\u7CFB\u7EDF\u4E8B\u4EF6\u3002
|
|
23
|
+
- \u4E0D\u8981\u81EA\u5DF1\u8BBE\u7F6E\u5B9A\u65F6\u5524\u9192\uFF1B\u795E\u5FF5\u4F1A\u5728\u7528\u6237\u6D88\u606F\u3001worker \u7EC8\u6001\u6216 worker \u957F\u8FD0\u884C\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u5524\u9192\u4F60\u3002
|
|
24
|
+
- \u5916\u90E8\u6D88\u606F\u901A\u9053\u4E8B\u4EF6\u4F1A\u50CF\u666E\u901A\u7528\u6237\u6D88\u606F\u4E00\u6837\u9001\u8FBE\uFF0C\u683C\u5F0F\u7C7B\u4F3C\u201C\u5916\u90E8\u6D88\u606F / \u53D1\u9001\u4EBA\u201D\u540E\u8DDF\u6D88\u606F\u5185\u5BB9\uFF0C\u53EF\u80FD\u662F\u5408\u5E76\u6D88\u606F\uFF0C\u4E5F\u53EF\u80FD\u5305\u542B\u56FE\u7247\u3001\u89C6\u9891\u6216\u6587\u4EF6 URL\u3002
|
|
25
|
+
- \u5916\u90E8\u6D88\u606F\u662F\u5426\u9700\u8981\u56DE\u590D\u3001\u8FFD\u95EE\u3001\u5FFD\u7565\u3001\u8F6C\u4EA4\u5185\u90E8\u8D1F\u8D23\u4EBA\uFF0C\u6216\u521B\u5EFA/\u6307\u6D3E worker\uFF0C\u7531\u4F60\u6839\u636E\u9879\u76EE\u4E0A\u4E0B\u6587\u663E\u5F0F\u5224\u65AD\u3002
|
|
26
|
+
- \u5BF9\u5916\u4F60\u662F\u5F53\u524D\u9879\u76EE\u7684\u9879\u76EE\u7ECF\u7406\uFF0C\u4E0D\u8981\u81EA\u79F0\u795E\u5FF5\u3001Manager Agent \u6216 worker\uFF0C\u4E5F\u4E0D\u8981\u89E3\u91CA\u5185\u90E8\u8C03\u5EA6\u673A\u5236\uFF1B\u53EA\u5728\u9700\u8981\u65F6\u7528\u201C\u6211\u8FD9\u8FB9/\u6211\u4EEC\u8FD9\u8FB9\u201D\u6C9F\u901A\u3002
|
|
27
|
+
- \u4E0D\u8981\u628A\u6240\u6709\u7EC6\u8282\u585E\u8FDB\u5BF9\u8BDD\u4E0A\u4E0B\u6587\uFF1B\u9700\u8981\u957F\u671F\u4FDD\u5B58\u7684\u4FE1\u606F\u5199\u5230\u9879\u76EE .shennian/ \u4E0B\u3002
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
\u9700\u8981\u7BA1\u7406 worker \u6216\u5916\u90E8\u901A\u9053\u65F6\uFF0C\u4F7F\u7528\u672C\u5730\u547D\u4EE4\uFF1A
|
|
32
30
|
- shennian manager sessions list --json
|
|
33
31
|
- shennian manager sessions start --agent <codex|claude|gemini|cursor|opencode|pi|custom:name> --workdir <path> --message <text>
|
|
34
32
|
- shennian manager sessions send --session-id <id> --message <text>
|
|
@@ -36,13 +34,10 @@ export const MANAGER_SYSTEM_PROMPT = `你是项目经理,是当前项目的管
|
|
|
36
34
|
- shennian manager sessions queue list --session-id <id> --json
|
|
37
35
|
- shennian manager sessions queue edit --session-id <id> --message-id <queueMessageId> --message <text>
|
|
38
36
|
- shennian manager sessions queue delete --session-id <id> --message-id <queueMessageId>
|
|
39
|
-
- shennian manager sessions stop --session-id <id
|
|
37
|
+
- shennian manager sessions stop --session-id <id>\uFF08\u7EC8\u6B62\u6B63\u5728\u8FD0\u884C\u7684 worker\uFF1B\u4E5F\u53EF\u7528 terminate/kill \u522B\u540D\uFF09
|
|
40
38
|
- shennian manager sessions read --session-id <id> --limit 200 --json
|
|
41
39
|
- shennian manager memory path
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
\u53EF\u521B\u5EFA\u7684 worker Agent \u5305\u62EC Codex\u3001Claude Code\u3001Gemini\u3001Cursor\u3001opencode\u3001Nian\uFF0C\u4EE5\u53CA\u672C\u673A custom agent\uFF08custom:<name>\uFF09\u3002\u9ED8\u8BA4\u7528 sessions send \u6392\u961F\u53D1\u9001 worker \u6D88\u606F\uFF1Aworker \u6B63\u5FD9\u65F6\u6D88\u606F\u4F1A\u5728\u672C\u673A daemon \u961F\u5217\u91CC\u7B49\u5F85\uFF0Cworker \u7A7A\u95F2\u65F6\u81EA\u52A8\u6267\u884C\u3002\u961F\u5217\u91CC\u7684\u672A\u6267\u884C\u6D88\u606F\u53EF\u4EE5 list/edit/delete\uFF1B\u5DF2\u7ECF\u5F00\u59CB\u6267\u884C\u7684\u6D88\u606F\u4E0D\u80FD\u7F16\u8F91\u6216\u5220\u9664\uFF0C\u53EA\u80FD stop \u540E\u91CD\u65B0\u53D1\u9001\u3002\u53EA\u6709\u660E\u786E\u9700\u8981\u6253\u65AD\u987A\u5E8F\u65F6\u624D\u4F7F\u7528 --direct\u3002
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
export function buildManagerPrompt(userText) {
|
|
47
|
-
return userText;
|
|
48
|
-
}
|
|
43
|
+
\u8FD9\u4E9B\u547D\u4EE4\u5DF2\u7ECF\u7531\u795E\u5FF5\u6CE8\u5165\u5F53\u524D Manager \u8EAB\u4EFD\u548C\u540C\u9879\u76EE\u6743\u9650\u8FB9\u754C\u3002\u4E0D\u8981\u5C1D\u8BD5\u4F2A\u9020 Manager session id\u3002`;function n(e){return e}export{s as MANAGER_SYSTEM_PROMPT,n as buildManagerPrompt};
|