@oatelauser/crosschat 1.0.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +25 -0
  3. package/README.md +244 -0
  4. package/dist/claude/deliver.js +33 -0
  5. package/dist/claude/deliver.js.map +1 -0
  6. package/dist/claude/frame.js +16 -0
  7. package/dist/claude/frame.js.map +1 -0
  8. package/dist/claude/key-file.js +45 -0
  9. package/dist/claude/key-file.js.map +1 -0
  10. package/dist/claude/registry.js +79 -0
  11. package/dist/claude/registry.js.map +1 -0
  12. package/dist/claude/resolve-exe.js +31 -0
  13. package/dist/claude/resolve-exe.js.map +1 -0
  14. package/dist/cli.js +270 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/codex/client.js +130 -0
  17. package/dist/codex/client.js.map +1 -0
  18. package/dist/codex/deliver.js +162 -0
  19. package/dist/codex/deliver.js.map +1 -0
  20. package/dist/codex/discovery.js +45 -0
  21. package/dist/codex/discovery.js.map +1 -0
  22. package/dist/codex/queue.js +71 -0
  23. package/dist/codex/queue.js.map +1 -0
  24. package/dist/codex/rollout-meta.js +118 -0
  25. package/dist/codex/rollout-meta.js.map +1 -0
  26. package/dist/codex/rpc.js +153 -0
  27. package/dist/codex/rpc.js.map +1 -0
  28. package/dist/codex/transport.js +357 -0
  29. package/dist/codex/transport.js.map +1 -0
  30. package/dist/commands/claude-wrapper.js +28 -0
  31. package/dist/commands/claude-wrapper.js.map +1 -0
  32. package/dist/commands/doctor.js +169 -0
  33. package/dist/commands/doctor.js.map +1 -0
  34. package/dist/commands/install-skills.js +26 -0
  35. package/dist/commands/install-skills.js.map +1 -0
  36. package/dist/commands/send.js +122 -0
  37. package/dist/commands/send.js.map +1 -0
  38. package/dist/commands/status.js +77 -0
  39. package/dist/commands/status.js.map +1 -0
  40. package/dist/envelope.js +34 -0
  41. package/dist/envelope.js.map +1 -0
  42. package/dist/errors.js +15 -0
  43. package/dist/errors.js.map +1 -0
  44. package/dist/identity.js +42 -0
  45. package/dist/identity.js.map +1 -0
  46. package/dist/outbox.js +172 -0
  47. package/dist/outbox.js.map +1 -0
  48. package/dist/platform/pipe-transport.js +73 -0
  49. package/dist/platform/pipe-transport.js.map +1 -0
  50. package/dist/platform/process-inspector.js +15 -0
  51. package/dist/platform/process-inspector.js.map +1 -0
  52. package/dist/rate-limit.js +49 -0
  53. package/dist/rate-limit.js.map +1 -0
  54. package/dist/ref.js +64 -0
  55. package/dist/ref.js.map +1 -0
  56. package/dist/resolve.js +30 -0
  57. package/dist/resolve.js.map +1 -0
  58. package/package.json +47 -0
  59. package/skills/crosschat/SKILL.md +65 -0
@@ -0,0 +1,357 @@
1
+ import { spawn, spawnSync } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import process from 'node:process';
6
+ import { Duplex } from 'node:stream';
7
+ import WebSocket from 'ws';
8
+ import { MultichatError } from '../errors.js';
9
+ const MAX_STDERR_BYTES = 64 * 1024;
10
+ const SPAWN_TIMEOUT_MS = 10_000;
11
+ const WS_CLOSE_TIMEOUT_MS = 2_000;
12
+ const GRACEFUL_EXIT_MS = 2_000;
13
+ const KILL_EXIT_TIMEOUT_MS = 1_500;
14
+ /**
15
+ * Resolve the codex executable. On Windows the npm shim (`codex.cmd`) cannot be
16
+ * spawned without a shell, so the native exe is located explicitly.
17
+ */
18
+ export function resolveCodexExecutable() {
19
+ const override = process.env.CROSSCHAT_CODEX_BIN;
20
+ if (override)
21
+ return override;
22
+ if (process.platform !== 'win32')
23
+ return 'codex';
24
+ const candidates = [];
25
+ if (process.env.APPDATA) {
26
+ candidates.push(join(process.env.APPDATA, 'npm', 'node_modules', '@openai', 'codex', 'node_modules', '@openai', 'codex-win32-x64', 'vendor', 'x86_64-pc-windows-msvc', 'bin', 'codex.exe'));
27
+ }
28
+ const where = spawnSync('where.exe', ['codex'], { encoding: 'utf8' });
29
+ if (where.status === 0) {
30
+ for (const line of where.stdout.split(/\r?\n/)) {
31
+ if (line.trim().toLowerCase().endsWith('.exe'))
32
+ candidates.push(line.trim());
33
+ }
34
+ }
35
+ candidates.push(join(homedir(), '.codex', 'packages', 'app-server-daemon', 'current', 'bin', 'codex.exe'));
36
+ const found = candidates.find((candidate) => existsSync(candidate));
37
+ if (!found) {
38
+ throw new MultichatError('CODEX_PROXY_SPAWN_FAILED', `codex executable not found; tried: ${candidates.join(', ')}`);
39
+ }
40
+ return found;
41
+ }
42
+ /** stdin/stdout of the proxy child exposed as one socket-like Duplex for ws. */
43
+ class ChildProxyDuplex extends Duplex {
44
+ child;
45
+ constructor(child) {
46
+ super();
47
+ this.child = child;
48
+ this.on('error', () => undefined);
49
+ child.stdout.pause();
50
+ child.stdout.on('data', (chunk) => {
51
+ if (!this.push(chunk))
52
+ child.stdout.pause();
53
+ });
54
+ child.stdout.on('end', () => this.push(null));
55
+ child.stdout.on('error', () => this.destroy(new Error('proxy stdout failed')));
56
+ child.stdin.on('error', () => this.destroy(new Error('proxy stdin failed')));
57
+ child.on('error', () => this.destroy(new Error('proxy process failed')));
58
+ }
59
+ _read() {
60
+ this.child.stdout.resume();
61
+ }
62
+ _write(chunk, encoding, callback) {
63
+ if (!this.child.stdin.writable) {
64
+ callback(new Error('proxy stdin closed'));
65
+ return;
66
+ }
67
+ this.child.stdin.write(chunk, encoding, callback);
68
+ }
69
+ _final(callback) {
70
+ this.child.stdin.end(callback);
71
+ }
72
+ _destroy(error, callback) {
73
+ this.child.stdin.destroy();
74
+ this.child.stdout.destroy();
75
+ callback(error);
76
+ }
77
+ setKeepAlive() {
78
+ return this;
79
+ }
80
+ setNoDelay() {
81
+ return this;
82
+ }
83
+ setTimeout(_timeout, callback) {
84
+ if (callback)
85
+ this.once('timeout', callback);
86
+ return this;
87
+ }
88
+ }
89
+ /** Bounded stderr capture: keeps at most MAX_STDERR_BYTES for diagnostics. */
90
+ class StderrCapture {
91
+ chunks = [];
92
+ bytes = 0;
93
+ push(chunk) {
94
+ if (this.bytes >= MAX_STDERR_BYTES)
95
+ return;
96
+ const room = MAX_STDERR_BYTES - this.bytes;
97
+ const kept = chunk.length > room ? chunk.subarray(0, room) : chunk;
98
+ this.chunks.push(kept);
99
+ this.bytes += kept.length;
100
+ }
101
+ text() {
102
+ return Buffer.concat(this.chunks).toString('utf8');
103
+ }
104
+ }
105
+ function waitForSpawn(child, timeoutMs) {
106
+ return new Promise((resolve, reject) => {
107
+ let settled = false;
108
+ const finish = (error) => {
109
+ if (settled)
110
+ return;
111
+ settled = true;
112
+ clearTimeout(timer);
113
+ child.off('spawn', onSpawn);
114
+ child.off('error', onError);
115
+ if (error)
116
+ reject(error);
117
+ else
118
+ resolve();
119
+ };
120
+ const onSpawn = () => finish();
121
+ const onError = (error) => finish(error);
122
+ const timer = setTimeout(() => finish(new Error('codex proxy spawn timed out')), timeoutMs);
123
+ child.once('spawn', onSpawn);
124
+ child.once('error', onError);
125
+ });
126
+ }
127
+ function closeWebSocket(socket) {
128
+ return new Promise((resolve) => {
129
+ let settled = false;
130
+ const finish = () => {
131
+ if (settled)
132
+ return;
133
+ settled = true;
134
+ clearTimeout(timer);
135
+ socket.off('close', finish);
136
+ resolve();
137
+ };
138
+ const timer = setTimeout(() => {
139
+ socket.terminate();
140
+ finish();
141
+ }, WS_CLOSE_TIMEOUT_MS);
142
+ socket.once('close', finish);
143
+ if (socket.readyState === WebSocket.CLOSED)
144
+ finish();
145
+ else
146
+ socket.close(1000);
147
+ });
148
+ }
149
+ function waitForExit(child, timeoutMs) {
150
+ if (child.exitCode !== null || child.signalCode !== null)
151
+ return Promise.resolve(true);
152
+ return new Promise((resolve) => {
153
+ let settled = false;
154
+ const finish = (closed) => {
155
+ if (settled)
156
+ return;
157
+ settled = true;
158
+ clearTimeout(timer);
159
+ child.off('close', onClose);
160
+ resolve(closed);
161
+ };
162
+ const onClose = () => finish(true);
163
+ const timer = setTimeout(() => finish(false), timeoutMs);
164
+ child.once('close', onClose);
165
+ });
166
+ }
167
+ /** Kill the exact process tree this session spawned. Never throws. */
168
+ async function killProxyTree(child) {
169
+ try {
170
+ child.stdin.end();
171
+ }
172
+ catch {
173
+ // already closed
174
+ }
175
+ if (await waitForExit(child, GRACEFUL_EXIT_MS))
176
+ return;
177
+ const pid = child.pid;
178
+ if (pid !== undefined) {
179
+ if (process.platform === 'win32') {
180
+ spawnSync('taskkill.exe', ['/PID', String(pid), '/T', '/F'], { stdio: 'ignore' });
181
+ }
182
+ else {
183
+ try {
184
+ child.kill('SIGKILL');
185
+ }
186
+ catch {
187
+ // already dead
188
+ }
189
+ }
190
+ }
191
+ await waitForExit(child, KILL_EXIT_TIMEOUT_MS);
192
+ }
193
+ function rawDataToBuffer(data) {
194
+ if (Buffer.isBuffer(data))
195
+ return data;
196
+ if (data instanceof ArrayBuffer)
197
+ return Buffer.from(data);
198
+ return Buffer.concat(data);
199
+ }
200
+ /** Default channel factory: WebSocket upgrade over the proxy stdio duplex. */
201
+ export async function wsChannelFactory(duplex) {
202
+ const socket = new WebSocket('ws://localhost/rpc', {
203
+ createConnection: () => {
204
+ // Node's HTTP upgrade client waits for the socket 'connect' event; the
205
+ // child stdio duplex has no TCP tuning knobs to apply.
206
+ queueMicrotask(() => duplex.emit('connect'));
207
+ return duplex;
208
+ },
209
+ followRedirects: false,
210
+ handshakeTimeout: 10_000,
211
+ maxPayload: 16 * 1024 * 1024,
212
+ perMessageDeflate: false,
213
+ });
214
+ // Permanent sink so a pre-listener error cannot become an uncaught exception.
215
+ socket.on('error', () => undefined);
216
+ await new Promise((resolve, reject) => {
217
+ let settled = false;
218
+ const finish = (error) => {
219
+ if (settled)
220
+ return;
221
+ settled = true;
222
+ socket.off('open', onOpen);
223
+ socket.off('error', onError);
224
+ socket.off('unexpected-response', onUnexpected);
225
+ if (error) {
226
+ socket.terminate();
227
+ reject(error);
228
+ }
229
+ else {
230
+ resolve();
231
+ }
232
+ };
233
+ const onOpen = () => finish();
234
+ const onError = () => finish(new MultichatError('CODEX_TRANSPORT_CLOSED', 'codex proxy connection failed.'));
235
+ const onUnexpected = () => finish(new MultichatError('CODEX_PROTOCOL_ERROR', 'codex proxy rejected the WebSocket upgrade.'));
236
+ socket.once('open', onOpen);
237
+ socket.once('error', onError);
238
+ socket.once('unexpected-response', onUnexpected);
239
+ });
240
+ const messageListeners = new Set();
241
+ const closeListeners = new Set();
242
+ socket.on('message', (data, isBinary) => {
243
+ if (isBinary)
244
+ return;
245
+ const payload = rawDataToBuffer(data).toString('utf8');
246
+ for (const listener of [...messageListeners])
247
+ listener(payload);
248
+ });
249
+ socket.on('close', () => {
250
+ for (const listener of [...closeListeners])
251
+ listener();
252
+ });
253
+ return {
254
+ send(payload) {
255
+ // Write failures surface through the 'error'/'close' events, which fail
256
+ // every pending request; the per-request timeout bounds hangs.
257
+ socket.send(payload, () => undefined);
258
+ },
259
+ onMessage(listener) {
260
+ messageListeners.add(listener);
261
+ return () => messageListeners.delete(listener);
262
+ },
263
+ onClose(listener) {
264
+ closeListeners.add(listener);
265
+ return () => closeListeners.delete(listener);
266
+ },
267
+ close() {
268
+ return closeWebSocket(socket);
269
+ },
270
+ get stderrText() {
271
+ return '';
272
+ },
273
+ };
274
+ }
275
+ /**
276
+ * Spawn `codex app-server proxy`, perform the WebSocket upgrade over its
277
+ * stdio, and return the session. The caller must close() it; close() closes
278
+ * the WebSocket, ends the proxy stdin, and force-kills the spawned tree if it
279
+ * does not exit on its own.
280
+ */
281
+ export async function openCodexProxySession(options = {}) {
282
+ const command = options.executable ?? resolveCodexExecutable();
283
+ const doSpawn = options.spawnProxy ??
284
+ ((cmd, args) => spawn(cmd, [...args], {
285
+ stdio: ['pipe', 'pipe', 'pipe'],
286
+ shell: false,
287
+ windowsHide: true,
288
+ env: process.env,
289
+ }));
290
+ const channelFactory = options.channelFactory ?? wsChannelFactory;
291
+ let child;
292
+ try {
293
+ child = doSpawn(command, ['app-server', 'proxy']);
294
+ }
295
+ catch (err) {
296
+ throw new MultichatError('CODEX_PROXY_SPAWN_FAILED', `Failed to spawn the codex app-server proxy (${command}).`, { cause: err });
297
+ }
298
+ const stderr = new StderrCapture();
299
+ child.stderr.on('data', (chunk) => stderr.push(chunk));
300
+ const duplex = new ChildProxyDuplex(child);
301
+ const spawnError = (message, cause) => new MultichatError('CODEX_PROXY_SPAWN_FAILED', message, {
302
+ cause: cause ?? (stderr.text() ? new Error(stderr.text()) : undefined),
303
+ stderrText: stderr.text(),
304
+ });
305
+ try {
306
+ await waitForSpawn(child, SPAWN_TIMEOUT_MS);
307
+ }
308
+ catch (err) {
309
+ duplex.destroy();
310
+ await killProxyTree(child).catch(() => undefined);
311
+ throw spawnError(`The codex app-server proxy failed to start (${command}).`, err);
312
+ }
313
+ let channel;
314
+ try {
315
+ channel = await channelFactory(duplex);
316
+ }
317
+ catch (err) {
318
+ duplex.destroy();
319
+ await killProxyTree(child).catch(() => undefined);
320
+ if (err instanceof MultichatError) {
321
+ // The ws-level error knows nothing of the child; carry the bounded
322
+ // stderr capture out so callers can report why the proxy died.
323
+ if (err.stderrText === undefined && stderr.text() !== '')
324
+ err.stderrText = stderr.text();
325
+ throw err;
326
+ }
327
+ throw spawnError('The codex app-server proxy channel could not be established.', err);
328
+ }
329
+ const channelWithStderr = {
330
+ send: (payload) => channel.send(payload),
331
+ onMessage: (listener) => channel.onMessage(listener),
332
+ onClose: (listener) => channel.onClose(listener),
333
+ close: () => channel.close(),
334
+ get stderrText() {
335
+ return stderr.text();
336
+ },
337
+ };
338
+ let closePromise;
339
+ const session = {
340
+ channel: channelWithStderr,
341
+ close() {
342
+ closePromise ??= (async () => {
343
+ // Close the WebSocket first (close frame through the proxy), then reap
344
+ // the child tree.
345
+ await channel.close().catch(() => undefined);
346
+ await killProxyTree(child).catch(() => undefined);
347
+ })();
348
+ return closePromise;
349
+ },
350
+ };
351
+ // If the server side goes away, reap our own process tree.
352
+ channel.onClose(() => {
353
+ void session.close().catch(() => undefined);
354
+ });
355
+ return session;
356
+ }
357
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/codex/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { MultichatError } from '../errors.js';
3
+ import { resolveClaudeExe } from '../claude/resolve-exe.js';
4
+ /**
5
+ * `crosschat claude [args...]`: start the real claude CLI with
6
+ * `crossSessionInbound: accept` so peer sessions can inject messages
7
+ * (ticket 002: without it inbound frames sit in parity hold).
8
+ */
9
+ const INBOUND_SETTINGS = JSON.stringify({ crossSessionInbound: 'accept' });
10
+ export function defaultClaudeWrapperDeps() {
11
+ return {
12
+ resolveExe: () => resolveClaudeExe(),
13
+ spawnInherit: (exe, args) => new Promise((resolve, reject) => {
14
+ const child = spawn(exe, args, { stdio: 'inherit' });
15
+ child.on('error', reject);
16
+ child.on('close', (code) => resolve(code ?? 1));
17
+ }),
18
+ };
19
+ }
20
+ export async function runClaudeWrapper(args, deps = defaultClaudeWrapperDeps()) {
21
+ if (args.some((token) => token === '--settings' || token.startsWith('--settings='))) {
22
+ throw new MultichatError('SETTINGS_CONFLICT', 'crosschat claude passes its own --settings {"crossSessionInbound":"accept"}. '
23
+ + 'Merge that JSON into your settings file and start claude directly instead.');
24
+ }
25
+ const exe = deps.resolveExe();
26
+ return deps.spawnInherit(exe, ['--settings', INBOUND_SETTINGS, ...args]);
27
+ }
28
+ //# sourceMappingURL=claude-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-wrapper.js","sourceRoot":"","sources":["../../src/commands/claude-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;GAIG;AAEH,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC;AAQ3E,MAAM,UAAU,wBAAwB;IACtC,OAAO;QACL,UAAU,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE;QACpC,YAAY,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAC1B,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACrD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC;KACL,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAuB,EACvB,OAA0B,wBAAwB,EAAE;IAEpD,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,YAAY,IAAI,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QACpF,MAAM,IAAI,cAAc,CACtB,mBAAmB,EACnB,+EAA+E;cAC3E,4EAA4E,CACjF,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IAC9B,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,169 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import process from 'node:process';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { listClaudeSessions } from '../claude/registry.js';
8
+ import { resolveClaudeExe } from '../claude/resolve-exe.js';
9
+ import { resolveCodexExecutable } from '../codex/transport.js';
10
+ import { defaultOutboxDir, outboxSummary } from '../outbox.js';
11
+ /** 开窗投递 (B8) requires app-server 0.160. */
12
+ const CODEX_MIN_VERSION = [0, 160, 0];
13
+ export function defaultDoctorDeps() {
14
+ return {
15
+ nodeVersion: process.versions.node,
16
+ env: process.env,
17
+ resolveClaude: () => resolveClaudeExe(),
18
+ listClaudeSessions: () => listClaudeSessions(),
19
+ codexBin: () => resolveCodexExecutable(),
20
+ run: (bin, args) => spawnSync(bin, [...args], { encoding: 'utf8' }),
21
+ exists: existsSync,
22
+ readFile: (path) => {
23
+ try {
24
+ return readFileSync(path, 'utf8');
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ },
30
+ homeDir: () => homedir(),
31
+ listOutbox: () => outboxSummary(defaultOutboxDir()),
32
+ repoSkillContent: () => {
33
+ try {
34
+ // dist/commands/ is two levels below the package root (same as install-skills).
35
+ return readFileSync(fileURLToPath(new URL('../../skills/crosschat/SKILL.md', import.meta.url)), 'utf8');
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ },
41
+ };
42
+ }
43
+ export function runDoctor(deps = defaultDoctorDeps()) {
44
+ const lines = [];
45
+ let pass = 0;
46
+ let warn = 0;
47
+ let bad = 0;
48
+ const ok = (line) => {
49
+ pass += 1;
50
+ lines.push(line);
51
+ };
52
+ const attention = (line) => {
53
+ warn += 1;
54
+ lines.push(line);
55
+ };
56
+ const fail = (line) => {
57
+ bad += 1;
58
+ lines.push(line);
59
+ };
60
+ // 1. Node >= 22
61
+ const major = Number.parseInt(deps.nodeVersion.split('.')[0] ?? '', 10);
62
+ if (Number.isInteger(major) && major >= 22)
63
+ ok(`✅ Node v${deps.nodeVersion} (≥22)`);
64
+ else
65
+ fail(`❌ Node v${deps.nodeVersion || '?'}(需 ≥22)`);
66
+ // 2. claude CLI + registry + routable sessions
67
+ try {
68
+ const exe = deps.resolveClaude();
69
+ const scan = deps.listClaudeSessions();
70
+ if (scan.sessions.length === 0) {
71
+ attention(`⚠️ claude CLI 可解析(${exe}),但当前无可路由会话(crosschat claude 启动的会话才可接收)`);
72
+ }
73
+ else {
74
+ ok(`✅ claude CLI ${exe};可路由会话 ${scan.sessions.length} 个`);
75
+ }
76
+ if (scan.malformed > 0)
77
+ attention(`⚠️ claude 注册表 ${scan.malformed} 个损坏条目(已忽略)`);
78
+ }
79
+ catch {
80
+ fail('❌ claude CLI 不可解析(CLAUDE_EXE_NOT_FOUND);确认 claude 已安装');
81
+ }
82
+ // 3+4. codex CLI and daemon versions (daemon needs the binary resolved first)
83
+ let codexBin;
84
+ try {
85
+ codexBin = deps.codexBin();
86
+ }
87
+ catch {
88
+ // reported below
89
+ }
90
+ if (codexBin === undefined) {
91
+ fail('❌ codex CLI 未找到;安装 codex 后重试');
92
+ fail('❌ codex daemon 无法检查(codex CLI 缺失);安装后运行: codex app-server daemon start');
93
+ }
94
+ else {
95
+ const v = deps.run(codexBin, ['--version']);
96
+ const ver = v.status === 0 ? parseSemver(v.stdout) : undefined;
97
+ if (ver === undefined)
98
+ attention(`⚠️ codex CLI 存在,但版本无法解析:${firstLine(v.stdout) || `(exit ${v.status ?? 'null'})`}`);
99
+ else if (cmpVersion(ver, CODEX_MIN_VERSION) < 0) {
100
+ attention(`⚠️ codex CLI ${ver.join('.')}(<${CODEX_MIN_VERSION.join('.')}:开窗投递需升级)`);
101
+ }
102
+ else
103
+ ok(`✅ codex CLI ${ver.join('.')}`);
104
+ const d = deps.run(codexBin, ['app-server', 'daemon', 'version']);
105
+ const daemonVer = d.status === 0 ? parseSemver(d.stdout) : undefined;
106
+ if (daemonVer === undefined) {
107
+ fail('❌ codex daemon 未运行;先执行: codex app-server daemon start');
108
+ }
109
+ else if (cmpVersion(daemonVer, CODEX_MIN_VERSION) < 0) {
110
+ attention(`⚠️ codex daemon ${daemonVer.join('.')}(<${CODEX_MIN_VERSION.join('.')}:开窗投递需升级后重启 daemon)`);
111
+ }
112
+ else
113
+ ok(`✅ codex daemon ${daemonVer.join('.')}`);
114
+ }
115
+ // 5. skill installation (and repo comparison when locatable)
116
+ const repo = deps.repoSkillContent();
117
+ for (const root of ['.claude', '.codex']) {
118
+ const side = root === '.claude' ? 'claude' : 'codex';
119
+ const path = join(deps.homeDir(), root, 'skills', 'crosschat', 'SKILL.md');
120
+ if (!deps.exists(path)) {
121
+ attention(`⚠️ ${side} 侧 skill 未安装(${path});运行 crosschat install-skills`);
122
+ continue;
123
+ }
124
+ if (repo === undefined) {
125
+ ok(`✅ ${side} 侧 skill 已安装(仓库 SKILL.md 未定位到,跳过版本比对)`);
126
+ continue;
127
+ }
128
+ if (deps.readFile(path) === repo)
129
+ ok(`✅ ${side} 侧 skill 与仓库版本一致`);
130
+ else
131
+ attention(`⚠️ ${side} 侧 skill 与仓库版本不一致;重跑 crosschat install-skills`);
132
+ }
133
+ // 6. dual caller-identity residue in this shell
134
+ const claudeSide = (deps.env.CLAUDE_CODE_MESSAGING_SOCKET ?? '') !== '';
135
+ const codexSide = (deps.env.CODEX_THREAD_ID ?? '') !== '' || (deps.env.CODEX_SESSION_ID ?? '') !== '';
136
+ if (claudeSide && codexSide) {
137
+ attention('⚠️ 双身份残留:CLAUDE_CODE_* 与 CODEX_* 并存(CALLER_IDENTITY_CONFLICT 风险);' +
138
+ '临时自纠: env -u CLAUDE_CODE_MESSAGING_SOCKET -u CLAUDE_CODE_MESSAGING_TOKEN -u CLAUDE_CODE_SESSION_ID <命令>');
139
+ }
140
+ else
141
+ ok('✅ 无双身份残留');
142
+ // 7. outbox state (informational)
143
+ const parked = deps.listOutbox();
144
+ if (parked.length === 0) {
145
+ ok('✅ 发件箱空(无暂存消息)');
146
+ }
147
+ else {
148
+ for (const { threadId, count } of parked) {
149
+ pass += 1;
150
+ lines.push(`⏳ 线程 ${threadId.slice(0, 8)} 暂存 ${count} 条(将在对方空闲时自动补投)`);
151
+ }
152
+ }
153
+ lines.push(`结论: ${pass} 项通过,${warn} 项警告,${bad} 项错误`);
154
+ return { output: lines.join('\n'), failed: bad > 0 };
155
+ }
156
+ function parseSemver(text) {
157
+ const m = text.match(/(\d+)\.(\d+)\.(\d+)/);
158
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : undefined;
159
+ }
160
+ function cmpVersion(a, b) {
161
+ for (let i = 0; i < 3; i++)
162
+ if (a[i] !== b[i])
163
+ return a[i] - b[i];
164
+ return 0;
165
+ }
166
+ function firstLine(text) {
167
+ return text.split(/\r?\n/, 1)[0] ?? '';
168
+ }
169
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { cpSync, mkdirSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ export function defaultInstallSkillsDeps() {
6
+ return {
7
+ // src/commands/ and dist/commands/ are both two levels below the package root.
8
+ sourceDir: () => fileURLToPath(new URL('../../skills/crosschat', import.meta.url)),
9
+ defaultRoot: () => homedir(),
10
+ };
11
+ }
12
+ const DEST_ROOTS = ['.claude', '.codex'];
13
+ /** Copies the skill over both destinations (mkdir + overwrite = idempotent); returns the installed paths. */
14
+ export function runInstallSkills(args, deps = defaultInstallSkillsDeps()) {
15
+ const source = deps.sourceDir();
16
+ const root = args.dir ?? deps.defaultRoot();
17
+ const installed = [];
18
+ for (const destRoot of DEST_ROOTS) {
19
+ const dest = join(root, destRoot, 'skills', 'crosschat');
20
+ mkdirSync(dest, { recursive: true });
21
+ cpSync(source, dest, { recursive: true });
22
+ installed.push(dest);
23
+ }
24
+ return installed;
25
+ }
26
+ //# sourceMappingURL=install-skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-skills.js","sourceRoot":"","sources":["../../src/commands/install-skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAmBzC,MAAM,UAAU,wBAAwB;IACtC,OAAO;QACL,+EAA+E;QAC/E,SAAS,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClF,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAU,CAAC;AAElD,6GAA6G;AAC7G,MAAM,UAAU,gBAAgB,CAC9B,IAAuB,EACvB,OAA0B,wBAAwB,EAAE;IAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QACzD,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}