shennian 0.2.5 → 0.2.6
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/package.json +1 -1
- package/dist/bin/shennian.d.ts +0 -2
- package/dist/bin/shennian.js +0 -2
- package/dist/src/agents/adapter.d.ts +0 -35
- package/dist/src/agents/adapter.js +0 -19
- package/dist/src/agents/claude.d.ts +0 -25
- package/dist/src/agents/claude.js +0 -234
- package/dist/src/agents/codex.d.ts +0 -49
- package/dist/src/agents/codex.js +0 -794
- package/dist/src/agents/command-spec.d.ts +0 -36
- package/dist/src/agents/command-spec.js +0 -303
- package/dist/src/agents/cursor.d.ts +0 -22
- package/dist/src/agents/cursor.js +0 -248
- package/dist/src/agents/custom.d.ts +0 -30
- package/dist/src/agents/custom.js +0 -210
- package/dist/src/agents/detect.d.ts +0 -9
- package/dist/src/agents/detect.js +0 -46
- package/dist/src/agents/gemini.d.ts +0 -17
- package/dist/src/agents/gemini.js +0 -172
- package/dist/src/agents/model-registry/cache.d.ts +0 -4
- package/dist/src/agents/model-registry/cache.js +0 -37
- package/dist/src/agents/model-registry/discovery.d.ts +0 -4
- package/dist/src/agents/model-registry/discovery.js +0 -161
- package/dist/src/agents/model-registry/parsers.d.ts +0 -11
- package/dist/src/agents/model-registry/parsers.js +0 -349
- package/dist/src/agents/model-registry/runner.d.ts +0 -6
- package/dist/src/agents/model-registry/runner.js +0 -29
- package/dist/src/agents/model-registry/service.d.ts +0 -6
- package/dist/src/agents/model-registry/service.js +0 -71
- package/dist/src/agents/model-registry/types.d.ts +0 -30
- package/dist/src/agents/model-registry/types.js +0 -8
- package/dist/src/agents/model-registry.d.ts +0 -13
- package/dist/src/agents/model-registry.js +0 -15
- package/dist/src/agents/openclaw.d.ts +0 -20
- package/dist/src/agents/openclaw.js +0 -273
- package/dist/src/agents/pi.d.ts +0 -51
- package/dist/src/agents/pi.js +0 -793
- package/dist/src/commands/agent.d.ts +0 -2
- package/dist/src/commands/agent.js +0 -131
- package/dist/src/commands/daemon.d.ts +0 -35
- package/dist/src/commands/daemon.js +0 -612
- package/dist/src/commands/pair-qr.d.ts +0 -4
- package/dist/src/commands/pair-qr.js +0 -6
- package/dist/src/commands/pair.d.ts +0 -8
- package/dist/src/commands/pair.js +0 -162
- package/dist/src/commands/upgrade.d.ts +0 -5
- package/dist/src/commands/upgrade.js +0 -145
- package/dist/src/config/index.d.ts +0 -32
- package/dist/src/config/index.js +0 -31
- package/dist/src/fs/handler.d.ts +0 -26
- package/dist/src/fs/handler.js +0 -130
- package/dist/src/fs/security.d.ts +0 -2
- package/dist/src/fs/security.js +0 -32
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +0 -277
- package/dist/src/log-reporter.d.ts +0 -18
- package/dist/src/log-reporter.js +0 -16
- package/dist/src/native-fusion/parsers.d.ts +0 -12
- package/dist/src/native-fusion/parsers.js +0 -687
- package/dist/src/native-fusion/service.d.ts +0 -25
- package/dist/src/native-fusion/service.js +0 -176
- package/dist/src/native-fusion/state.d.ts +0 -3
- package/dist/src/native-fusion/state.js +0 -22
- package/dist/src/native-fusion/types.d.ts +0 -24
- package/dist/src/native-fusion/types.js +0 -1
- package/dist/src/region.d.ts +0 -15
- package/dist/src/region.js +0 -99
- package/dist/src/relay/client.d.ts +0 -62
- package/dist/src/relay/client.js +0 -311
- package/dist/src/session/handlers/agents.d.ts +0 -4
- package/dist/src/session/handlers/agents.js +0 -55
- package/dist/src/session/handlers/chat.d.ts +0 -4
- package/dist/src/session/handlers/chat.js +0 -326
- package/dist/src/session/handlers/control.d.ts +0 -5
- package/dist/src/session/handlers/control.js +0 -57
- package/dist/src/session/handlers/fs.d.ts +0 -10
- package/dist/src/session/handlers/fs.js +0 -256
- package/dist/src/session/manager.d.ts +0 -28
- package/dist/src/session/manager.js +0 -174
- package/dist/src/session/store.d.ts +0 -7
- package/dist/src/session/store.js +0 -46
- package/dist/src/session/types.d.ts +0 -35
- package/dist/src/session/types.js +0 -4
- package/dist/src/upgrade/engine.d.ts +0 -64
- package/dist/src/upgrade/engine.js +0 -238
package/dist/src/index.js
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
// @arch docs/architecture/cli/daemon.md
|
|
2
|
-
// @test src/__tests__/agents-e2e.ts
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import os from 'node:os';
|
|
6
|
-
import fs from 'node:fs';
|
|
7
|
-
import { loadConfig, saveConfig, configPath, getShennianDir, resolveShennianPath } from './config/index.js';
|
|
8
|
-
import { CliRelayClient } from './relay/client.js';
|
|
9
|
-
import { registerPairCommand, runSmartStart } from './commands/pair.js';
|
|
10
|
-
import { registerDaemonCommand } from './commands/daemon.js';
|
|
11
|
-
import { registerAgentCommand } from './commands/agent.js';
|
|
12
|
-
import { registerUpgradeCommand } from './commands/upgrade.js';
|
|
13
|
-
import { SessionManager } from './session/manager.js';
|
|
14
|
-
import { SERVERS, regionToUrl, urlToRegion } from './region.js';
|
|
15
|
-
import { getCurrentVersion, handleStartupCrashCheck, checkForUpdate } from './upgrade/engine.js';
|
|
16
|
-
import { detectAgents } from './agents/detect.js';
|
|
17
|
-
const cliVersion = getCurrentVersion();
|
|
18
|
-
import { getCachedAgentInfos, resolveAgentInfos } from './agents/model-registry.js';
|
|
19
|
-
import { initCliLogReporter, reportLog } from './log-reporter.js';
|
|
20
|
-
import { NativeSessionFusionService } from './native-fusion/service.js';
|
|
21
|
-
const SHENNIAN_DIR = getShennianDir();
|
|
22
|
-
const PID_FILE = resolveShennianPath('daemon.pid');
|
|
23
|
-
function httpToWs(url) {
|
|
24
|
-
return url.replace(/^https:\/\//, 'wss://').replace(/^http:\/\//, 'ws://');
|
|
25
|
-
}
|
|
26
|
-
function formatDisconnectInfo(info) {
|
|
27
|
-
const parts = [
|
|
28
|
-
`trigger=${info.trigger ?? 'unknown'}`,
|
|
29
|
-
`phase=${info.phase}`,
|
|
30
|
-
`code=${info.code ?? 'unknown'}`,
|
|
31
|
-
`attempt=${info.reconnectAttempt}`,
|
|
32
|
-
];
|
|
33
|
-
if (info.reason)
|
|
34
|
-
parts.push(`reason=${info.reason}`);
|
|
35
|
-
if (info.error)
|
|
36
|
-
parts.push(`error=${info.error}`);
|
|
37
|
-
return parts.join(' ');
|
|
38
|
-
}
|
|
39
|
-
const program = new Command();
|
|
40
|
-
program
|
|
41
|
-
.name('shennian')
|
|
42
|
-
.description('Shennian — AI Agent Mobile Console')
|
|
43
|
-
.version(cliVersion);
|
|
44
|
-
program
|
|
45
|
-
.option('--api <url>', 'Server URL override')
|
|
46
|
-
.option('--name <name>', 'Machine name', os.hostname())
|
|
47
|
-
.action(async (opts) => {
|
|
48
|
-
const config = loadConfig();
|
|
49
|
-
const serverUrl = opts.api ?? config.serverUrl ?? undefined;
|
|
50
|
-
await runSmartStart(serverUrl, opts.name);
|
|
51
|
-
});
|
|
52
|
-
// start: internal command used by the daemon process
|
|
53
|
-
program
|
|
54
|
-
.command('start', { hidden: true })
|
|
55
|
-
.description('(internal) Connect to relay server, called by daemon')
|
|
56
|
-
.option('--api <url>', 'Server URL override')
|
|
57
|
-
.action(async (opts) => {
|
|
58
|
-
const envFile = resolveShennianPath('env.json');
|
|
59
|
-
try {
|
|
60
|
-
const saved = JSON.parse(fs.readFileSync(envFile, 'utf-8'));
|
|
61
|
-
for (const [k, v] of Object.entries(saved)) {
|
|
62
|
-
if (!process.env[k])
|
|
63
|
-
process.env[k] = v;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
// env.json may not exist yet
|
|
68
|
-
}
|
|
69
|
-
// Single-instance guard: kill any existing daemon before starting
|
|
70
|
-
const pidFile = resolveShennianPath('daemon.pid');
|
|
71
|
-
try {
|
|
72
|
-
const oldPid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
73
|
-
if (oldPid && oldPid !== process.pid) {
|
|
74
|
-
try {
|
|
75
|
-
process.kill(oldPid, 0);
|
|
76
|
-
console.log(`[${new Date().toISOString()}] daemon already running (PID ${oldPid}), skipping duplicate start`);
|
|
77
|
-
process.exit(0);
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// Stale pid; continue booting and overwrite it below.
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch { /* noop */ }
|
|
85
|
-
fs.writeFileSync(pidFile, String(process.pid));
|
|
86
|
-
process.on('exit', () => { try {
|
|
87
|
-
fs.unlinkSync(pidFile);
|
|
88
|
-
}
|
|
89
|
-
catch { /* noop */ } });
|
|
90
|
-
// Crash detection: if we're recovering from a failed upgrade, rollback and exit
|
|
91
|
-
const didRollback = await handleStartupCrashCheck();
|
|
92
|
-
if (didRollback) {
|
|
93
|
-
console.log(`[${new Date().toISOString()}] Rolled back to previous version, restarting...`);
|
|
94
|
-
process.exit(0);
|
|
95
|
-
}
|
|
96
|
-
const config = loadConfig();
|
|
97
|
-
if (!config.machineToken) {
|
|
98
|
-
console.error(chalk.red('✗ Not paired yet. Run: shennian'));
|
|
99
|
-
process.exit(1);
|
|
100
|
-
}
|
|
101
|
-
const serverUrl = opts.api ?? config.serverUrl ?? SERVERS.global.url;
|
|
102
|
-
const wsBase = httpToWs(serverUrl);
|
|
103
|
-
const wsUrl = `${wsBase}/relay/machine`;
|
|
104
|
-
const cliVersion = getCurrentVersion();
|
|
105
|
-
const detectedAgents = detectAgents();
|
|
106
|
-
const agentList = detectedAgents.map((a) => a.type);
|
|
107
|
-
const cachedAgentInfos = getCachedAgentInfos(detectedAgents);
|
|
108
|
-
if (config.machineId) {
|
|
109
|
-
initCliLogReporter(serverUrl, config.machineId);
|
|
110
|
-
}
|
|
111
|
-
console.log(`[${new Date().toISOString()}] Connecting to ${wsUrl}... (v${cliVersion}) agents: ${agentList.join(',')}`);
|
|
112
|
-
reportLog({ level: 'info', wsEvent: 'daemon.start', metadata: { version: cliVersion, agents: agentList } });
|
|
113
|
-
let nativeFusion = null;
|
|
114
|
-
const client = new CliRelayClient({
|
|
115
|
-
serverUrl: wsUrl,
|
|
116
|
-
machineToken: config.machineToken,
|
|
117
|
-
cliVersion,
|
|
118
|
-
agentList,
|
|
119
|
-
onConnected: () => {
|
|
120
|
-
console.log(`[${new Date().toISOString()}] ✓ Connected`);
|
|
121
|
-
reportLog({ level: 'info', wsEvent: 'daemon.connected' });
|
|
122
|
-
if (cachedAgentInfos.some((agent) => agent.models.length > 0)) {
|
|
123
|
-
client.sendEvent({
|
|
124
|
-
type: 'event',
|
|
125
|
-
event: 'machine.agents',
|
|
126
|
-
payload: {
|
|
127
|
-
agentList,
|
|
128
|
-
agents: cachedAgentInfos,
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
void resolveAgentInfos(detectedAgents, {
|
|
133
|
-
serverUrl: config.serverUrl ?? serverUrl,
|
|
134
|
-
authToken: config.machineToken ?? config.accessToken,
|
|
135
|
-
}).then((agents) => {
|
|
136
|
-
if (JSON.stringify(agents) === JSON.stringify(cachedAgentInfos))
|
|
137
|
-
return;
|
|
138
|
-
client.sendEvent({
|
|
139
|
-
type: 'event',
|
|
140
|
-
event: 'machine.agents',
|
|
141
|
-
payload: {
|
|
142
|
-
agentList,
|
|
143
|
-
agents,
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
}).catch(() => { });
|
|
147
|
-
import('./upgrade/engine.js').then(({ readUpgradeAttempt, clearUpgradeAttempt }) => {
|
|
148
|
-
const attempt = readUpgradeAttempt();
|
|
149
|
-
clearUpgradeAttempt();
|
|
150
|
-
if (attempt) {
|
|
151
|
-
console.log(`[${new Date().toISOString()}] [upgrade] Reporting success: ${attempt.from} → ${attempt.to}`);
|
|
152
|
-
client.sendEvent({
|
|
153
|
-
type: 'event',
|
|
154
|
-
event: 'upgrade',
|
|
155
|
-
payload: { state: 'success', machineId: 'self', from: attempt.from, to: attempt.to },
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}).catch(() => { });
|
|
159
|
-
void scheduleAutoUpgrade(client, config.autoUpgrade ?? 'patch');
|
|
160
|
-
nativeFusion?.handleConnected();
|
|
161
|
-
},
|
|
162
|
-
onDisconnected: (info) => {
|
|
163
|
-
console.log(`[${new Date().toISOString()}] ⚠ Disconnected, reconnecting... ${formatDisconnectInfo(info)}`);
|
|
164
|
-
reportLog({
|
|
165
|
-
level: 'warn',
|
|
166
|
-
wsEvent: 'daemon.disconnected',
|
|
167
|
-
metadata: {
|
|
168
|
-
code: info.code,
|
|
169
|
-
reason: info.reason,
|
|
170
|
-
error: info.error,
|
|
171
|
-
phase: info.phase,
|
|
172
|
-
trigger: info.trigger,
|
|
173
|
-
reconnectAttempt: info.reconnectAttempt,
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
},
|
|
177
|
-
onReq: (req) => {
|
|
178
|
-
console.log(`[${new Date().toISOString()}] [req] ${req.method}`);
|
|
179
|
-
reportLog({ level: 'info', type: 'ws', wsEvent: req.method, wsDirection: 'in', traceId: req.traceId });
|
|
180
|
-
void sessionManager.handleReq(req);
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
nativeFusion = process.env.SHENNIAN_NATIVE_FUSION_DISABLED === '1'
|
|
184
|
-
? null
|
|
185
|
-
: new NativeSessionFusionService(client);
|
|
186
|
-
const sessionManager = new SessionManager(client, nativeFusion);
|
|
187
|
-
fs.mkdirSync(SHENNIAN_DIR, { recursive: true });
|
|
188
|
-
fs.writeFileSync(PID_FILE, String(process.pid));
|
|
189
|
-
client.connect();
|
|
190
|
-
process.stdin.resume();
|
|
191
|
-
const shutdown = () => {
|
|
192
|
-
console.log(chalk.gray('\nDisconnecting...'));
|
|
193
|
-
reportLog({ level: 'info', wsEvent: 'daemon.stop' });
|
|
194
|
-
sessionManager.cleanup();
|
|
195
|
-
nativeFusion?.stop();
|
|
196
|
-
client.disconnect();
|
|
197
|
-
try {
|
|
198
|
-
fs.unlinkSync(PID_FILE);
|
|
199
|
-
}
|
|
200
|
-
catch { /* noop */ }
|
|
201
|
-
process.exit(0);
|
|
202
|
-
};
|
|
203
|
-
process.on('SIGINT', shutdown);
|
|
204
|
-
process.on('SIGTERM', shutdown);
|
|
205
|
-
});
|
|
206
|
-
// config: view and modify settings
|
|
207
|
-
const configCmd = program
|
|
208
|
-
.command('config')
|
|
209
|
-
.description('View or modify configuration');
|
|
210
|
-
configCmd
|
|
211
|
-
.command('show', { isDefault: true })
|
|
212
|
-
.description('Show current configuration')
|
|
213
|
-
.action(() => {
|
|
214
|
-
console.log(`Config file: ${configPath}`);
|
|
215
|
-
const config = loadConfig();
|
|
216
|
-
const display = { ...config };
|
|
217
|
-
if (display.machineToken)
|
|
218
|
-
display.machineToken = display.machineToken.slice(0, 12) + '...';
|
|
219
|
-
if (display.serverUrl) {
|
|
220
|
-
const region = urlToRegion(display.serverUrl);
|
|
221
|
-
console.log(`Region: ${region} (${SERVERS[region].label})`);
|
|
222
|
-
}
|
|
223
|
-
console.log(JSON.stringify(display, null, 2));
|
|
224
|
-
});
|
|
225
|
-
configCmd
|
|
226
|
-
.command('set')
|
|
227
|
-
.description('Update a config value')
|
|
228
|
-
.argument('<key>', 'Config key (e.g. "server")')
|
|
229
|
-
.argument('<value>', 'Config value (e.g. "cn" or "global")')
|
|
230
|
-
.action((key, value) => {
|
|
231
|
-
const config = loadConfig();
|
|
232
|
-
if (key === 'server') {
|
|
233
|
-
if (value !== 'cn' && value !== 'global') {
|
|
234
|
-
console.error(chalk.red('✗ Value must be "cn" or "global"'));
|
|
235
|
-
process.exit(1);
|
|
236
|
-
}
|
|
237
|
-
const region = value;
|
|
238
|
-
config.serverUrl = regionToUrl(region);
|
|
239
|
-
saveConfig(config);
|
|
240
|
-
console.log(chalk.green(`✓ Server set to ${SERVERS[region].label}`));
|
|
241
|
-
console.log(chalk.yellow(' Restart the daemon for this to take effect: shennian daemon stop && shennian'));
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
console.error(chalk.red(`✗ Unknown config key: ${key}. Supported: server`));
|
|
245
|
-
process.exit(1);
|
|
246
|
-
});
|
|
247
|
-
registerPairCommand(program);
|
|
248
|
-
registerDaemonCommand(program);
|
|
249
|
-
registerAgentCommand(program);
|
|
250
|
-
registerUpgradeCommand(program);
|
|
251
|
-
program.parse();
|
|
252
|
-
// ─── Auto-upgrade helper ──────────────────────────────────────────────────────
|
|
253
|
-
async function scheduleAutoUpgrade(client, policy) {
|
|
254
|
-
if (policy === 'none')
|
|
255
|
-
return;
|
|
256
|
-
// Delay slightly so we don't hit npm on every cold start during development
|
|
257
|
-
await new Promise((r) => setTimeout(r, 30_000));
|
|
258
|
-
let result;
|
|
259
|
-
try {
|
|
260
|
-
result = await checkForUpdate();
|
|
261
|
-
}
|
|
262
|
-
catch {
|
|
263
|
-
return; // silently skip on network error
|
|
264
|
-
}
|
|
265
|
-
if (!result.hasUpdate)
|
|
266
|
-
return;
|
|
267
|
-
const { changeType, current, latest } = result;
|
|
268
|
-
// Respect the policy
|
|
269
|
-
if (policy === 'patch' && changeType !== 'patch')
|
|
270
|
-
return;
|
|
271
|
-
if (policy === 'minor' && changeType === 'major')
|
|
272
|
-
return;
|
|
273
|
-
console.log(`[${new Date().toISOString()}] [upgrade] ${current} → ${latest} (${changeType}), auto-upgrading...`);
|
|
274
|
-
const { handleUpgradeStart } = await import('./commands/upgrade.js');
|
|
275
|
-
// Use a dummy reqId since this is self-triggered
|
|
276
|
-
await handleUpgradeStart(client, 'auto-upgrade', latest);
|
|
277
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
-
type LogType = 'http' | 'ws' | 'internal';
|
|
3
|
-
type LogEntry = {
|
|
4
|
-
traceId?: string;
|
|
5
|
-
sessionId?: string;
|
|
6
|
-
type?: LogType;
|
|
7
|
-
level: LogLevel;
|
|
8
|
-
wsEvent?: string;
|
|
9
|
-
wsDirection?: 'in' | 'out';
|
|
10
|
-
errorMessage?: string;
|
|
11
|
-
errorStack?: string;
|
|
12
|
-
durationMs?: number;
|
|
13
|
-
metadata?: unknown;
|
|
14
|
-
};
|
|
15
|
-
export declare function initCliLogReporter(serverUrl: string, machineId: string): void;
|
|
16
|
-
export declare function generateTraceId(): string;
|
|
17
|
-
export declare function reportLog(entry: LogEntry): void;
|
|
18
|
-
export {};
|
package/dist/src/log-reporter.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import crypto from 'node:crypto';
|
|
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,12 +0,0 @@
|
|
|
1
|
-
import type { ParsedNativeEvent } from './types.js';
|
|
2
|
-
export declare function listCodexRolloutFiles(): string[];
|
|
3
|
-
export declare function listClaudeTranscriptFiles(): string[];
|
|
4
|
-
export declare function lookupClaudeTranscriptCwd(sourceSessionKey: string): string | null;
|
|
5
|
-
export declare function parseCodexRolloutChunk(filePath: string, startOffset: number): {
|
|
6
|
-
nextOffset: number;
|
|
7
|
-
events: ParsedNativeEvent[];
|
|
8
|
-
};
|
|
9
|
-
export declare function parseClaudeTranscriptChunk(filePath: string, startOffset: number): {
|
|
10
|
-
nextOffset: number;
|
|
11
|
-
events: ParsedNativeEvent[];
|
|
12
|
-
};
|