@feynmanzhang/open-party 0.1.4 → 0.1.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/dist/claude-code/{open-party-0.1.0 → open-party-0.1.6}/.claude-plugin/plugin.json +1 -1
- package/dist/claude-code/open-party-0.1.6/BUILD_INFO.json +6 -0
- package/dist/claude-code/{open-party-0.1.1 → open-party-0.1.6}/dist/hook-handler.js +113 -46
- package/dist/claude-code/{open-party-0.1.1 → open-party-0.1.6}/dist/mcp-server.js +156 -25
- package/dist/claude-code/{open-party-0.1.1 → open-party-0.1.6}/dist/party-server.js +549 -64
- package/dist/claude-code/{open-party-0.1.1 → open-party-0.1.6}/hooks/hooks.json +1 -1
- package/dist/claude-code/{open-party-0.1.1 → open-party-0.1.6}/package.json +1 -1
- package/dist/cli/index.js +750 -135
- package/dist/cli/index.js.map +1 -1
- package/dist/openclaw/open-party-0.1.5/BUILD_INFO.json +6 -0
- package/dist/openclaw/open-party-0.1.5/SKILL.md +127 -0
- package/dist/openclaw/open-party-0.1.5/dist/index.js +550 -0
- package/dist/openclaw/open-party-0.1.5/dist/party-server.js +5502 -0
- package/dist/openclaw/open-party-0.1.5/openclaw.plugin.json +28 -0
- package/dist/openclaw/open-party-0.1.5/package.json +12 -0
- package/dist/openclaw/open-party-0.1.5/skills/open-party/SKILL.md +90 -0
- package/dist/openclaw/open-party-0.1.6/BUILD_INFO.json +6 -0
- package/dist/openclaw/open-party-0.1.6/SKILL.md +127 -0
- package/dist/openclaw/open-party-0.1.6/dist/index.js +550 -0
- package/dist/openclaw/open-party-0.1.6/dist/party-server.js +5502 -0
- package/dist/openclaw/open-party-0.1.6/openclaw.plugin.json +28 -0
- package/dist/openclaw/open-party-0.1.6/package.json +12 -0
- package/dist/openclaw/open-party-0.1.6/skills/open-party/SKILL.md +90 -0
- package/dist/party-server.js +549 -64
- package/dist/party-server.js.map +1 -1
- package/package.json +35 -4
- package/dist/claude-code/open-party-0.1.1/.claude-plugin/plugin.json +0 -5
- package/dist/claude-code/open-party-0.1.1/.mcp.json +0 -9
- package/dist/claude-code/open-party-0.1.1/BUILD_INFO.json +0 -6
- package/dist/hook-handler.js +0 -555
- package/dist/hook-handler.js.map +0 -1
- package/dist/mcp-server.js +0 -21408
- package/dist/mcp-server.js.map +0 -1
- /package/dist/claude-code/{open-party-0.1.0 → open-party-0.1.6}/.mcp.json +0 -0
- /package/dist/claude-code/{open-party-0.1.1 → open-party-0.1.6}/skills/open-party/SKILL.md +0 -0
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// src/client/claude-code/src/hook-handler.ts
|
|
5
5
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
6
6
|
|
|
7
|
-
// src/client/
|
|
8
|
-
var
|
|
7
|
+
// src/client/shared/client.ts
|
|
8
|
+
var PartyHttpClient = class {
|
|
9
9
|
baseUrl;
|
|
10
10
|
timeout;
|
|
11
11
|
constructor(baseUrl = "http://127.0.0.1:8000", timeout = 5e3) {
|
|
@@ -76,11 +76,10 @@ var PartyServerClient = class {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
// src/client/
|
|
80
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
79
|
+
// src/client/shared/session-store.ts
|
|
80
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "fs";
|
|
81
81
|
import { join } from "path";
|
|
82
82
|
import { homedir } from "os";
|
|
83
|
-
import { randomUUID } from "crypto";
|
|
84
83
|
var SESSION_DIR = join(homedir(), ".open-party");
|
|
85
84
|
var SESSIONS_DIR = join(SESSION_DIR, "sessions");
|
|
86
85
|
var AGENTS_DIR = join(SESSION_DIR, "agents");
|
|
@@ -99,6 +98,9 @@ function readSession(sessionId) {
|
|
|
99
98
|
if (!existsSync(path)) return void 0;
|
|
100
99
|
return JSON.parse(readFileSync(path, "utf-8"));
|
|
101
100
|
}
|
|
101
|
+
|
|
102
|
+
// src/client/shared/id.ts
|
|
103
|
+
import { randomUUID } from "crypto";
|
|
102
104
|
function generateAgentId() {
|
|
103
105
|
return `agent-${randomUUID().slice(0, 12)}`;
|
|
104
106
|
}
|
|
@@ -134,7 +136,7 @@ function generateDisplayName() {
|
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
// src/client/claude-code/src/stdin-reader.ts
|
|
137
|
-
var SAFETY_TIMEOUT_MS =
|
|
139
|
+
var SAFETY_TIMEOUT_MS = 5e3;
|
|
138
140
|
var PARSE_DELAY_MS = 50;
|
|
139
141
|
function isStdinAvailable() {
|
|
140
142
|
try {
|
|
@@ -217,9 +219,17 @@ async function readJsonFromStdin() {
|
|
|
217
219
|
});
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
// src/client/
|
|
222
|
+
// src/client/shared/server-manager.ts
|
|
221
223
|
import { spawn, execSync } from "child_process";
|
|
222
|
-
import {
|
|
224
|
+
import {
|
|
225
|
+
existsSync as existsSync2,
|
|
226
|
+
readFileSync as readFileSync2,
|
|
227
|
+
writeFileSync as writeFileSync2,
|
|
228
|
+
unlinkSync as unlinkSync2,
|
|
229
|
+
mkdirSync as mkdirSync2,
|
|
230
|
+
openSync,
|
|
231
|
+
closeSync
|
|
232
|
+
} from "fs";
|
|
223
233
|
import { join as join2, resolve, dirname } from "path";
|
|
224
234
|
import { homedir as homedir2 } from "os";
|
|
225
235
|
import { fileURLToPath } from "url";
|
|
@@ -227,15 +237,19 @@ var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
227
237
|
var DEFAULT_PORT = parseInt(process.env.PARTY_PORT || "8000", 10);
|
|
228
238
|
var HEALTH_URL = `http://127.0.0.1:${DEFAULT_PORT}/proxy/health`;
|
|
229
239
|
var STARTUP_TIMEOUT = 1e4;
|
|
230
|
-
function
|
|
240
|
+
function pidFileDir() {
|
|
231
241
|
const pluginData = process.env.CLAUDE_PLUGIN_DATA || "";
|
|
232
|
-
if (pluginData) return
|
|
233
|
-
return join2(homedir2(), ".open-party"
|
|
242
|
+
if (pluginData) return pluginData;
|
|
243
|
+
return join2(homedir2(), ".open-party");
|
|
234
244
|
}
|
|
235
|
-
function
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
245
|
+
function pidFilePath() {
|
|
246
|
+
return join2(pidFileDir(), "server.pid");
|
|
247
|
+
}
|
|
248
|
+
function logFilePath() {
|
|
249
|
+
return join2(pidFileDir(), "server.log");
|
|
250
|
+
}
|
|
251
|
+
function lockFilePath() {
|
|
252
|
+
return join2(pidFileDir(), "starting.lock");
|
|
239
253
|
}
|
|
240
254
|
function pluginRoot() {
|
|
241
255
|
if (process.env.CLAUDE_PLUGIN_ROOT) return process.env.CLAUDE_PLUGIN_ROOT;
|
|
@@ -260,7 +274,7 @@ async function isRunning() {
|
|
|
260
274
|
}
|
|
261
275
|
}
|
|
262
276
|
function writePid(pid) {
|
|
263
|
-
const path =
|
|
277
|
+
const path = pidFilePath();
|
|
264
278
|
const dir = dirname(path);
|
|
265
279
|
if (!existsSync2(dir)) mkdirSync2(dir, { recursive: true });
|
|
266
280
|
writeFileSync2(path, String(pid));
|
|
@@ -268,14 +282,34 @@ function writePid(pid) {
|
|
|
268
282
|
async function sleep(ms) {
|
|
269
283
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
270
284
|
}
|
|
271
|
-
|
|
272
|
-
|
|
285
|
+
function acquireStartLock() {
|
|
286
|
+
const lockPath = lockFilePath();
|
|
287
|
+
try {
|
|
288
|
+
const fd = openSync(lockPath, "wx");
|
|
289
|
+
writeFileSync2(lockPath, String(process.pid));
|
|
290
|
+
return { acquired: true, fd };
|
|
291
|
+
} catch {
|
|
292
|
+
return { acquired: false, fd: -1 };
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function releaseStartLock(fd) {
|
|
296
|
+
if (fd >= 0) {
|
|
297
|
+
try {
|
|
298
|
+
closeSync(fd);
|
|
299
|
+
} catch {
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
unlinkSync2(lockFilePath());
|
|
304
|
+
} catch {
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
async function spawnAndWait() {
|
|
273
308
|
const serverScript = join2(pluginRoot(), "dist", "party-server.js");
|
|
274
309
|
if (!existsSync2(serverScript)) {
|
|
275
|
-
|
|
276
|
-
return;
|
|
310
|
+
throw new Error(`[Open Party] Server script not found: ${serverScript}`);
|
|
277
311
|
}
|
|
278
|
-
const logPath =
|
|
312
|
+
const logPath = logFilePath();
|
|
279
313
|
mkdirSync2(dirname(logPath), { recursive: true });
|
|
280
314
|
const logFd = openSync(logPath, "a");
|
|
281
315
|
const proc = spawn(process.execPath, [serverScript], {
|
|
@@ -293,10 +327,42 @@ async function ensureServerRunning() {
|
|
|
293
327
|
if (await isRunning()) return;
|
|
294
328
|
await sleep(500);
|
|
295
329
|
}
|
|
330
|
+
let alive = false;
|
|
296
331
|
try {
|
|
297
332
|
process.kill(proc.pid, 0);
|
|
333
|
+
alive = true;
|
|
298
334
|
} catch {
|
|
299
|
-
|
|
335
|
+
}
|
|
336
|
+
if (!alive) {
|
|
337
|
+
throw new Error(
|
|
338
|
+
`[Open Party] Server crashed during startup (PID ${proc.pid}). Check log: ${logPath}`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
throw new Error(
|
|
342
|
+
`[Open Party] Server did not become healthy within ${STARTUP_TIMEOUT}ms (PID ${proc.pid}). Check log: ${logPath}`
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
async function waitForExisting() {
|
|
346
|
+
const deadline = Date.now() + STARTUP_TIMEOUT;
|
|
347
|
+
while (Date.now() < deadline) {
|
|
348
|
+
if (await isRunning()) return;
|
|
349
|
+
await sleep(500);
|
|
350
|
+
}
|
|
351
|
+
throw new Error(
|
|
352
|
+
`[Open Party] Another process is starting the server but it did not become healthy within ${STARTUP_TIMEOUT}ms`
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
async function ensureServerRunning() {
|
|
356
|
+
if (await isRunning()) return;
|
|
357
|
+
const { acquired, fd } = acquireStartLock();
|
|
358
|
+
if (acquired) {
|
|
359
|
+
try {
|
|
360
|
+
await spawnAndWait();
|
|
361
|
+
} finally {
|
|
362
|
+
releaseStartLock(fd);
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
await waitForExisting();
|
|
300
366
|
}
|
|
301
367
|
}
|
|
302
368
|
|
|
@@ -304,7 +370,7 @@ async function ensureServerRunning() {
|
|
|
304
370
|
var PARTY_SERVER_URL = process.env.PARTY_SERVER_URL || "http://127.0.0.1:8000";
|
|
305
371
|
async function handleSessionStart(sessionId, source) {
|
|
306
372
|
await ensureServerRunning();
|
|
307
|
-
const client = new
|
|
373
|
+
const client = new PartyHttpClient(PARTY_SERVER_URL);
|
|
308
374
|
const existing = readSession(sessionId);
|
|
309
375
|
if (existing && (source === "clear" || source === "compact" || source === "resume")) {
|
|
310
376
|
const agentId2 = existing.agent_id;
|
|
@@ -313,53 +379,53 @@ async function handleSessionStart(sessionId, source) {
|
|
|
313
379
|
try {
|
|
314
380
|
await client.register(agentId2, displayName2, { type: "claude-code" });
|
|
315
381
|
console.error(`[Open Party] Re-registered as ${agentId2} (${displayName2})`);
|
|
316
|
-
} catch (
|
|
317
|
-
console.error(
|
|
382
|
+
} catch (error) {
|
|
383
|
+
console.error("[Open Party] Re-registration failed, will retry on next session:", error);
|
|
318
384
|
}
|
|
319
385
|
writeSession(sessionId, agentId2, displayName2, PARTY_SERVER_URL);
|
|
320
386
|
}
|
|
321
|
-
let
|
|
387
|
+
let agents = [];
|
|
322
388
|
let pendingMessages = [];
|
|
323
389
|
try {
|
|
324
|
-
|
|
390
|
+
agents = await client.listAgents();
|
|
325
391
|
if (source === "resume") {
|
|
326
392
|
pendingMessages = await client.checkMessages(agentId2);
|
|
327
393
|
}
|
|
328
|
-
} catch {
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error("[Open Party] Failed to fetch agent list/messages:", error);
|
|
329
396
|
}
|
|
330
|
-
outputContext(agentId2, displayName2,
|
|
397
|
+
outputContext(agentId2, displayName2, agents, pendingMessages);
|
|
331
398
|
return;
|
|
332
399
|
}
|
|
333
400
|
const agentId = generateAgentId();
|
|
334
401
|
const displayName = generateDisplayName();
|
|
335
402
|
try {
|
|
336
|
-
|
|
403
|
+
const [, agents] = await Promise.all([
|
|
404
|
+
client.register(agentId, displayName, { type: "claude-code" }),
|
|
405
|
+
client.listAgents()
|
|
406
|
+
]);
|
|
337
407
|
console.error(`[Open Party] Registered as ${agentId} (${displayName})`);
|
|
338
|
-
|
|
339
|
-
|
|
408
|
+
writeSession(sessionId, agentId, displayName, PARTY_SERVER_URL);
|
|
409
|
+
outputContext(agentId, displayName, agents, []);
|
|
410
|
+
return;
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error("[Open Party] Registration failed:", error);
|
|
340
413
|
writeSession(sessionId, agentId, displayName, PARTY_SERVER_URL);
|
|
341
414
|
outputContext(agentId, displayName, [], []);
|
|
342
415
|
return;
|
|
343
416
|
}
|
|
344
|
-
writeSession(sessionId, agentId, displayName, PARTY_SERVER_URL);
|
|
345
|
-
let agents = [];
|
|
346
|
-
try {
|
|
347
|
-
agents = await client.listAgents();
|
|
348
|
-
} catch {
|
|
349
|
-
}
|
|
350
|
-
outputContext(agentId, displayName, agents, []);
|
|
351
417
|
}
|
|
352
418
|
async function handleSessionEnd(sessionId) {
|
|
353
419
|
const session = readSession(sessionId);
|
|
354
420
|
if (!session) return;
|
|
355
421
|
const agentId = session.agent_id;
|
|
356
422
|
const serverUrl = session.server_url;
|
|
357
|
-
const client = new
|
|
423
|
+
const client = new PartyHttpClient(serverUrl);
|
|
358
424
|
try {
|
|
359
425
|
await client.remove(agentId);
|
|
360
426
|
console.error(`[Open Party] Unregistered ${agentId}`);
|
|
361
|
-
} catch (
|
|
362
|
-
console.error(
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error("[Open Party] Unregister failed:", error);
|
|
363
429
|
}
|
|
364
430
|
}
|
|
365
431
|
async function handleUserPromptSubmit(sessionId) {
|
|
@@ -367,11 +433,12 @@ async function handleUserPromptSubmit(sessionId) {
|
|
|
367
433
|
if (!session) return;
|
|
368
434
|
const agentId = session.agent_id;
|
|
369
435
|
const serverUrl = session.server_url;
|
|
370
|
-
const client = new
|
|
436
|
+
const client = new PartyHttpClient(serverUrl);
|
|
371
437
|
let messages;
|
|
372
438
|
try {
|
|
373
439
|
messages = await client.checkMessages(agentId);
|
|
374
|
-
} catch {
|
|
440
|
+
} catch (error) {
|
|
441
|
+
console.error("[Open Party] Failed to check messages:", error);
|
|
375
442
|
return;
|
|
376
443
|
}
|
|
377
444
|
if (!messages.length) return;
|
|
@@ -548,8 +615,8 @@ async function main() {
|
|
|
548
615
|
}
|
|
549
616
|
process.exit(0);
|
|
550
617
|
}
|
|
551
|
-
main().catch((
|
|
552
|
-
console.error(
|
|
618
|
+
main().catch((error) => {
|
|
619
|
+
console.error("[Open Party] Fatal:", error);
|
|
553
620
|
process.exit(1);
|
|
554
621
|
});
|
|
555
622
|
//# sourceMappingURL=hook-handler.js.map
|
|
@@ -21098,8 +21098,13 @@ var StdioServerTransport = class {
|
|
|
21098
21098
|
}
|
|
21099
21099
|
};
|
|
21100
21100
|
|
|
21101
|
-
// src/client/claude-code/src/
|
|
21102
|
-
|
|
21101
|
+
// src/client/claude-code/src/mcp-server.ts
|
|
21102
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
21103
|
+
import { join as join3 } from "path";
|
|
21104
|
+
import { homedir as homedir3 } from "os";
|
|
21105
|
+
|
|
21106
|
+
// src/client/shared/client.ts
|
|
21107
|
+
var PartyHttpClient = class {
|
|
21103
21108
|
baseUrl;
|
|
21104
21109
|
timeout;
|
|
21105
21110
|
constructor(baseUrl = "http://127.0.0.1:8000", timeout = 5e3) {
|
|
@@ -21170,11 +21175,10 @@ var PartyServerClient = class {
|
|
|
21170
21175
|
}
|
|
21171
21176
|
};
|
|
21172
21177
|
|
|
21173
|
-
// src/client/
|
|
21174
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
21178
|
+
// src/client/shared/session-store.ts
|
|
21179
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "fs";
|
|
21175
21180
|
import { join } from "path";
|
|
21176
21181
|
import { homedir } from "os";
|
|
21177
|
-
import { randomUUID } from "crypto";
|
|
21178
21182
|
var SESSION_DIR = join(homedir(), ".open-party");
|
|
21179
21183
|
var SESSIONS_DIR = join(SESSION_DIR, "sessions");
|
|
21180
21184
|
var AGENTS_DIR = join(SESSION_DIR, "agents");
|
|
@@ -21190,9 +21194,20 @@ function readSessionByAgent(agentId) {
|
|
|
21190
21194
|
return readSession(mapping.session_id);
|
|
21191
21195
|
}
|
|
21192
21196
|
|
|
21193
|
-
// src/client/
|
|
21197
|
+
// src/client/shared/id.ts
|
|
21198
|
+
import { randomUUID } from "crypto";
|
|
21199
|
+
|
|
21200
|
+
// src/client/shared/server-manager.ts
|
|
21194
21201
|
import { spawn, execSync } from "child_process";
|
|
21195
|
-
import {
|
|
21202
|
+
import {
|
|
21203
|
+
existsSync as existsSync2,
|
|
21204
|
+
readFileSync as readFileSync2,
|
|
21205
|
+
writeFileSync as writeFileSync2,
|
|
21206
|
+
unlinkSync as unlinkSync2,
|
|
21207
|
+
mkdirSync as mkdirSync2,
|
|
21208
|
+
openSync,
|
|
21209
|
+
closeSync
|
|
21210
|
+
} from "fs";
|
|
21196
21211
|
import { join as join2, resolve, dirname } from "path";
|
|
21197
21212
|
import { homedir as homedir2 } from "os";
|
|
21198
21213
|
import { fileURLToPath } from "url";
|
|
@@ -21200,15 +21215,19 @@ var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
21200
21215
|
var DEFAULT_PORT = parseInt(process.env.PARTY_PORT || "8000", 10);
|
|
21201
21216
|
var HEALTH_URL = `http://127.0.0.1:${DEFAULT_PORT}/proxy/health`;
|
|
21202
21217
|
var STARTUP_TIMEOUT = 1e4;
|
|
21203
|
-
function
|
|
21218
|
+
function pidFileDir() {
|
|
21204
21219
|
const pluginData = process.env.CLAUDE_PLUGIN_DATA || "";
|
|
21205
|
-
if (pluginData) return
|
|
21206
|
-
return join2(homedir2(), ".open-party"
|
|
21220
|
+
if (pluginData) return pluginData;
|
|
21221
|
+
return join2(homedir2(), ".open-party");
|
|
21207
21222
|
}
|
|
21208
|
-
function
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
|
|
21223
|
+
function pidFilePath() {
|
|
21224
|
+
return join2(pidFileDir(), "server.pid");
|
|
21225
|
+
}
|
|
21226
|
+
function logFilePath() {
|
|
21227
|
+
return join2(pidFileDir(), "server.log");
|
|
21228
|
+
}
|
|
21229
|
+
function lockFilePath() {
|
|
21230
|
+
return join2(pidFileDir(), "starting.lock");
|
|
21212
21231
|
}
|
|
21213
21232
|
function pluginRoot() {
|
|
21214
21233
|
if (process.env.CLAUDE_PLUGIN_ROOT) return process.env.CLAUDE_PLUGIN_ROOT;
|
|
@@ -21233,7 +21252,7 @@ async function isRunning() {
|
|
|
21233
21252
|
}
|
|
21234
21253
|
}
|
|
21235
21254
|
function writePid(pid) {
|
|
21236
|
-
const path =
|
|
21255
|
+
const path = pidFilePath();
|
|
21237
21256
|
const dir = dirname(path);
|
|
21238
21257
|
if (!existsSync2(dir)) mkdirSync2(dir, { recursive: true });
|
|
21239
21258
|
writeFileSync2(path, String(pid));
|
|
@@ -21241,14 +21260,34 @@ function writePid(pid) {
|
|
|
21241
21260
|
async function sleep(ms) {
|
|
21242
21261
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
21243
21262
|
}
|
|
21244
|
-
|
|
21245
|
-
|
|
21263
|
+
function acquireStartLock() {
|
|
21264
|
+
const lockPath = lockFilePath();
|
|
21265
|
+
try {
|
|
21266
|
+
const fd = openSync(lockPath, "wx");
|
|
21267
|
+
writeFileSync2(lockPath, String(process.pid));
|
|
21268
|
+
return { acquired: true, fd };
|
|
21269
|
+
} catch {
|
|
21270
|
+
return { acquired: false, fd: -1 };
|
|
21271
|
+
}
|
|
21272
|
+
}
|
|
21273
|
+
function releaseStartLock(fd) {
|
|
21274
|
+
if (fd >= 0) {
|
|
21275
|
+
try {
|
|
21276
|
+
closeSync(fd);
|
|
21277
|
+
} catch {
|
|
21278
|
+
}
|
|
21279
|
+
}
|
|
21280
|
+
try {
|
|
21281
|
+
unlinkSync2(lockFilePath());
|
|
21282
|
+
} catch {
|
|
21283
|
+
}
|
|
21284
|
+
}
|
|
21285
|
+
async function spawnAndWait() {
|
|
21246
21286
|
const serverScript = join2(pluginRoot(), "dist", "party-server.js");
|
|
21247
21287
|
if (!existsSync2(serverScript)) {
|
|
21248
|
-
|
|
21249
|
-
return;
|
|
21288
|
+
throw new Error(`[Open Party] Server script not found: ${serverScript}`);
|
|
21250
21289
|
}
|
|
21251
|
-
const logPath =
|
|
21290
|
+
const logPath = logFilePath();
|
|
21252
21291
|
mkdirSync2(dirname(logPath), { recursive: true });
|
|
21253
21292
|
const logFd = openSync(logPath, "a");
|
|
21254
21293
|
const proc = spawn(process.execPath, [serverScript], {
|
|
@@ -21266,16 +21305,48 @@ async function ensureServerRunning() {
|
|
|
21266
21305
|
if (await isRunning()) return;
|
|
21267
21306
|
await sleep(500);
|
|
21268
21307
|
}
|
|
21308
|
+
let alive = false;
|
|
21269
21309
|
try {
|
|
21270
21310
|
process.kill(proc.pid, 0);
|
|
21311
|
+
alive = true;
|
|
21271
21312
|
} catch {
|
|
21272
|
-
|
|
21313
|
+
}
|
|
21314
|
+
if (!alive) {
|
|
21315
|
+
throw new Error(
|
|
21316
|
+
`[Open Party] Server crashed during startup (PID ${proc.pid}). Check log: ${logPath}`
|
|
21317
|
+
);
|
|
21318
|
+
}
|
|
21319
|
+
throw new Error(
|
|
21320
|
+
`[Open Party] Server did not become healthy within ${STARTUP_TIMEOUT}ms (PID ${proc.pid}). Check log: ${logPath}`
|
|
21321
|
+
);
|
|
21322
|
+
}
|
|
21323
|
+
async function waitForExisting() {
|
|
21324
|
+
const deadline = Date.now() + STARTUP_TIMEOUT;
|
|
21325
|
+
while (Date.now() < deadline) {
|
|
21326
|
+
if (await isRunning()) return;
|
|
21327
|
+
await sleep(500);
|
|
21328
|
+
}
|
|
21329
|
+
throw new Error(
|
|
21330
|
+
`[Open Party] Another process is starting the server but it did not become healthy within ${STARTUP_TIMEOUT}ms`
|
|
21331
|
+
);
|
|
21332
|
+
}
|
|
21333
|
+
async function ensureServerRunning() {
|
|
21334
|
+
if (await isRunning()) return;
|
|
21335
|
+
const { acquired, fd } = acquireStartLock();
|
|
21336
|
+
if (acquired) {
|
|
21337
|
+
try {
|
|
21338
|
+
await spawnAndWait();
|
|
21339
|
+
} finally {
|
|
21340
|
+
releaseStartLock(fd);
|
|
21341
|
+
}
|
|
21342
|
+
} else {
|
|
21343
|
+
await waitForExisting();
|
|
21273
21344
|
}
|
|
21274
21345
|
}
|
|
21275
21346
|
|
|
21276
21347
|
// src/client/claude-code/src/mcp-server.ts
|
|
21277
21348
|
var PARTY_SERVER_URL = process.env.PARTY_SERVER_URL || "http://127.0.0.1:8000";
|
|
21278
|
-
var client = new
|
|
21349
|
+
var client = new PartyHttpClient(PARTY_SERVER_URL);
|
|
21279
21350
|
function validateAgent(agentId) {
|
|
21280
21351
|
const session = readSessionByAgent(agentId);
|
|
21281
21352
|
if (!session) {
|
|
@@ -21283,7 +21354,61 @@ function validateAgent(agentId) {
|
|
|
21283
21354
|
}
|
|
21284
21355
|
return null;
|
|
21285
21356
|
}
|
|
21286
|
-
var
|
|
21357
|
+
var HEARTBEAT_INTERVAL_MS = parseInt(process.env.HEARTBEAT_INTERVAL_MS || "15000", 10);
|
|
21358
|
+
var mySessionId = null;
|
|
21359
|
+
var myIdentity = null;
|
|
21360
|
+
function resolveSessionId() {
|
|
21361
|
+
const ppid = process.ppid;
|
|
21362
|
+
if (!ppid) return;
|
|
21363
|
+
const claudePath = join3(homedir3(), ".claude", "sessions", `${ppid}.json`);
|
|
21364
|
+
if (!existsSync3(claudePath)) return;
|
|
21365
|
+
let data;
|
|
21366
|
+
try {
|
|
21367
|
+
data = JSON.parse(readFileSync3(claudePath, "utf-8"));
|
|
21368
|
+
} catch {
|
|
21369
|
+
return;
|
|
21370
|
+
}
|
|
21371
|
+
mySessionId = data.sessionId || null;
|
|
21372
|
+
}
|
|
21373
|
+
function resolveAgentId() {
|
|
21374
|
+
if (myIdentity) return myIdentity;
|
|
21375
|
+
if (!mySessionId) return null;
|
|
21376
|
+
const partyPath = join3(homedir3(), ".open-party", "sessions", `${mySessionId}.json`);
|
|
21377
|
+
if (!existsSync3(partyPath)) return null;
|
|
21378
|
+
let data;
|
|
21379
|
+
try {
|
|
21380
|
+
data = JSON.parse(readFileSync3(partyPath, "utf-8"));
|
|
21381
|
+
} catch {
|
|
21382
|
+
return null;
|
|
21383
|
+
}
|
|
21384
|
+
const agentId = data.agent_id;
|
|
21385
|
+
if (!agentId) return null;
|
|
21386
|
+
myIdentity = { agent_id: agentId, display_name: data.display_name || agentId };
|
|
21387
|
+
return myIdentity;
|
|
21388
|
+
}
|
|
21389
|
+
function startHeartbeat() {
|
|
21390
|
+
setInterval(async () => {
|
|
21391
|
+
if (!mySessionId) resolveSessionId();
|
|
21392
|
+
const identity = resolveAgentId();
|
|
21393
|
+
if (!identity) return;
|
|
21394
|
+
try {
|
|
21395
|
+
await client.heartbeat(identity.agent_id);
|
|
21396
|
+
} catch (hbErr) {
|
|
21397
|
+
const msg = hbErr.message;
|
|
21398
|
+
if (/not registered/i.test(msg)) {
|
|
21399
|
+
console.warn(`[Open Party MCP] Agent removed by server, re-registering: ${identity.agent_id}`);
|
|
21400
|
+
try {
|
|
21401
|
+
await client.register(identity.agent_id, identity.display_name);
|
|
21402
|
+
} catch (regErr) {
|
|
21403
|
+
console.error("[Open Party MCP] Re-register failed:", regErr);
|
|
21404
|
+
}
|
|
21405
|
+
} else {
|
|
21406
|
+
console.error("[Open Party MCP] Heartbeat failed:", hbErr);
|
|
21407
|
+
}
|
|
21408
|
+
}
|
|
21409
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
21410
|
+
}
|
|
21411
|
+
var server = new McpServer({ name: "open-party", version: "0.1.6" });
|
|
21287
21412
|
server.tool(
|
|
21288
21413
|
"list_agents",
|
|
21289
21414
|
"List all agents currently online in the network.",
|
|
@@ -21304,6 +21429,7 @@ server.tool(
|
|
|
21304
21429
|
lines.push("", "> \u{1F4A1} Use `send_message` to reach any agent above.");
|
|
21305
21430
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
21306
21431
|
} catch (e) {
|
|
21432
|
+
console.error("[Open Party MCP] Error listing agents:", e);
|
|
21307
21433
|
return { content: [{ type: "text", text: `\u274C Error listing agents: ${e.message}` }] };
|
|
21308
21434
|
}
|
|
21309
21435
|
}
|
|
@@ -21331,6 +21457,7 @@ server.tool(
|
|
|
21331
21457
|
return { content: [{ type: "text", text: `\u26A0\uFE0F Send result: ${status}` }] };
|
|
21332
21458
|
}
|
|
21333
21459
|
} catch (e) {
|
|
21460
|
+
console.error("[Open Party MCP] Error sending message:", e);
|
|
21334
21461
|
return { content: [{ type: "text", text: `\u274C Error sending message: ${e.message}` }] };
|
|
21335
21462
|
}
|
|
21336
21463
|
}
|
|
@@ -21363,6 +21490,7 @@ server.tool(
|
|
|
21363
21490
|
lines.push("---", "", "\u{1F4A1} Reply with `send_message` if needed.");
|
|
21364
21491
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
21365
21492
|
} catch (e) {
|
|
21493
|
+
console.error("[Open Party MCP] Error checking messages:", e);
|
|
21366
21494
|
return { content: [{ type: "text", text: `\u274C Error checking messages: ${e.message}` }] };
|
|
21367
21495
|
}
|
|
21368
21496
|
}
|
|
@@ -21392,17 +21520,20 @@ server.tool(
|
|
|
21392
21520
|
lines.push("---");
|
|
21393
21521
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
21394
21522
|
} catch (e) {
|
|
21523
|
+
console.error("[Open Party MCP] Error fetching history:", e);
|
|
21395
21524
|
return { content: [{ type: "text", text: `\u274C Error fetching history: ${e.message}` }] };
|
|
21396
21525
|
}
|
|
21397
21526
|
}
|
|
21398
21527
|
);
|
|
21399
21528
|
async function main() {
|
|
21400
21529
|
await ensureServerRunning();
|
|
21530
|
+
resolveSessionId();
|
|
21531
|
+
startHeartbeat();
|
|
21401
21532
|
const transport = new StdioServerTransport();
|
|
21402
21533
|
await server.connect(transport);
|
|
21403
21534
|
}
|
|
21404
|
-
main().catch((
|
|
21405
|
-
console.error(
|
|
21535
|
+
main().catch((error2) => {
|
|
21536
|
+
console.error("[Open Party MCP] Fatal:", error2);
|
|
21406
21537
|
process.exit(1);
|
|
21407
21538
|
});
|
|
21408
21539
|
//# sourceMappingURL=mcp-server.js.map
|