@shipers-dev/multi 0.4.2 → 0.5.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.
- package/dist/index.js +47 -14
- package/package.json +1 -1
- package/src/index.ts +46 -12
package/dist/index.js
CHANGED
|
@@ -5381,7 +5381,7 @@ var LOG_PATH = join(MULTI_DIR, "logs", "agent.log");
|
|
|
5381
5381
|
var SKILLS_DIR = join(MULTI_DIR, "skills");
|
|
5382
5382
|
var STOP_PATH = join(MULTI_DIR, "stop.flag");
|
|
5383
5383
|
var TASKS_DB_PATH = join(MULTI_DIR, "tasks.db");
|
|
5384
|
-
var VERSION = "0.
|
|
5384
|
+
var VERSION = "0.5.0";
|
|
5385
5385
|
var COMMANDS = {
|
|
5386
5386
|
setup: "Register this device with a workspace",
|
|
5387
5387
|
connect: "Connect device to realtime hub and execute assigned tasks",
|
|
@@ -5414,6 +5414,7 @@ async function main() {
|
|
|
5414
5414
|
options: {
|
|
5415
5415
|
help: { type: "boolean", default: false, short: "h" },
|
|
5416
5416
|
version: { type: "boolean", default: false },
|
|
5417
|
+
detach: { type: "boolean", default: false, short: "d" },
|
|
5417
5418
|
name: { type: "string" },
|
|
5418
5419
|
workspace: { type: "string" },
|
|
5419
5420
|
agent: { type: "string" },
|
|
@@ -5437,7 +5438,11 @@ async function main() {
|
|
|
5437
5438
|
break;
|
|
5438
5439
|
case "connect":
|
|
5439
5440
|
case "start":
|
|
5440
|
-
|
|
5441
|
+
if (args.values.detach) {
|
|
5442
|
+
await cmdConnectDetached(apiUrl);
|
|
5443
|
+
} else {
|
|
5444
|
+
await cmdConnect(apiUrl, config);
|
|
5445
|
+
}
|
|
5441
5446
|
break;
|
|
5442
5447
|
case "link":
|
|
5443
5448
|
await cmdLink(apiUrl, config, args.values.agent);
|
|
@@ -5473,10 +5478,11 @@ Commands:
|
|
|
5473
5478
|
|
|
5474
5479
|
Options:
|
|
5475
5480
|
--name <name> Device name
|
|
5476
|
-
--workspace <id> Workspace ID
|
|
5477
5481
|
--agent <id> Agent ID (for link)
|
|
5478
|
-
--api <url> API URL
|
|
5479
|
-
--
|
|
5482
|
+
--api <url> API URL
|
|
5483
|
+
-d, --detach Run connect in background (daemon)
|
|
5484
|
+
-v, --version Print version
|
|
5485
|
+
-h, --help Show this help
|
|
5480
5486
|
|
|
5481
5487
|
Examples:
|
|
5482
5488
|
multi-agent setup --name "My Mac" --workspace ws_xxx
|
|
@@ -5719,6 +5725,28 @@ async function cmdConnect(apiUrl, config) {
|
|
|
5719
5725
|
}
|
|
5720
5726
|
}
|
|
5721
5727
|
}
|
|
5728
|
+
async function cmdConnectDetached(apiUrl) {
|
|
5729
|
+
if (existsSync2(PID_PATH)) {
|
|
5730
|
+
const pid = Number(readFileSync2(PID_PATH, "utf8").trim());
|
|
5731
|
+
if (pid && isRunning(pid)) {
|
|
5732
|
+
console.log(`\u274C Daemon already running (pid ${pid}).`);
|
|
5733
|
+
process.exit(1);
|
|
5734
|
+
}
|
|
5735
|
+
}
|
|
5736
|
+
ensureDirs();
|
|
5737
|
+
const logFd = Bun.file(LOG_PATH);
|
|
5738
|
+
const args = Bun.argv.slice(1).filter((a) => a !== "-d" && a !== "--detach");
|
|
5739
|
+
const proc = Bun.spawn([process.execPath, ...args, "--api", apiUrl], {
|
|
5740
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
5741
|
+
env: { ...process.env, MULTI_DETACHED: "1" }
|
|
5742
|
+
});
|
|
5743
|
+
proc.unref?.();
|
|
5744
|
+
await sleep(500);
|
|
5745
|
+
console.log(`\u2705 Daemon started in background (pid ${proc.pid}).`);
|
|
5746
|
+
console.log(` Tail logs: multi-agent logs`);
|
|
5747
|
+
console.log(` Stop: multi-agent stop`);
|
|
5748
|
+
process.exit(0);
|
|
5749
|
+
}
|
|
5722
5750
|
async function pickFreePort() {
|
|
5723
5751
|
for (let i = 0;i < 10; i++) {
|
|
5724
5752
|
const p = 40000 + Math.floor(Math.random() * 20000);
|
|
@@ -5776,16 +5804,21 @@ async function handleRunTask(apiUrl, deviceId, task, detected) {
|
|
|
5776
5804
|
let liveBody = "";
|
|
5777
5805
|
let hadError = false;
|
|
5778
5806
|
let hasAssistantText = false;
|
|
5779
|
-
|
|
5807
|
+
let liveCommentPromise = null;
|
|
5808
|
+
const ensureLiveComment = () => {
|
|
5780
5809
|
if (liveCommentId)
|
|
5781
|
-
return;
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5810
|
+
return Promise.resolve();
|
|
5811
|
+
if (!liveCommentPromise) {
|
|
5812
|
+
liveCommentPromise = apiClient.post(`${apiUrl}/api/issues/${issueId}/comments`, {
|
|
5813
|
+
author_type: "agent",
|
|
5814
|
+
author_id: task.agent_id,
|
|
5815
|
+
author_name: "agent",
|
|
5816
|
+
body: "\u2026"
|
|
5817
|
+
}).then((res) => {
|
|
5818
|
+
liveCommentId = res.data?.id;
|
|
5819
|
+
});
|
|
5820
|
+
}
|
|
5821
|
+
return liveCommentPromise;
|
|
5789
5822
|
};
|
|
5790
5823
|
const patchLive = async (body) => {
|
|
5791
5824
|
if (!liveCommentId)
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -16,7 +16,7 @@ const LOG_PATH = join(MULTI_DIR, 'logs', 'agent.log');
|
|
|
16
16
|
const SKILLS_DIR = join(MULTI_DIR, 'skills');
|
|
17
17
|
const STOP_PATH = join(MULTI_DIR, 'stop.flag');
|
|
18
18
|
const TASKS_DB_PATH = join(MULTI_DIR, 'tasks.db');
|
|
19
|
-
const VERSION = '0.
|
|
19
|
+
const VERSION = '0.5.0';
|
|
20
20
|
|
|
21
21
|
const COMMANDS = {
|
|
22
22
|
setup: 'Register this device with a workspace',
|
|
@@ -54,6 +54,7 @@ async function main() {
|
|
|
54
54
|
options: {
|
|
55
55
|
help: { type: 'boolean', default: false, short: 'h' },
|
|
56
56
|
version: { type: 'boolean', default: false },
|
|
57
|
+
detach: { type: 'boolean', default: false, short: 'd' },
|
|
57
58
|
name: { type: 'string' },
|
|
58
59
|
workspace: { type: 'string' },
|
|
59
60
|
agent: { type: 'string' },
|
|
@@ -80,7 +81,11 @@ async function main() {
|
|
|
80
81
|
break;
|
|
81
82
|
case 'connect':
|
|
82
83
|
case 'start':
|
|
83
|
-
|
|
84
|
+
if (args.values.detach) {
|
|
85
|
+
await cmdConnectDetached(apiUrl);
|
|
86
|
+
} else {
|
|
87
|
+
await cmdConnect(apiUrl, config);
|
|
88
|
+
}
|
|
84
89
|
break;
|
|
85
90
|
case 'link':
|
|
86
91
|
await cmdLink(apiUrl, config, args.values.agent);
|
|
@@ -117,10 +122,11 @@ Commands:
|
|
|
117
122
|
|
|
118
123
|
Options:
|
|
119
124
|
--name <name> Device name
|
|
120
|
-
--workspace <id> Workspace ID
|
|
121
125
|
--agent <id> Agent ID (for link)
|
|
122
|
-
--api <url> API URL
|
|
123
|
-
--
|
|
126
|
+
--api <url> API URL
|
|
127
|
+
-d, --detach Run connect in background (daemon)
|
|
128
|
+
-v, --version Print version
|
|
129
|
+
-h, --help Show this help
|
|
124
130
|
|
|
125
131
|
Examples:
|
|
126
132
|
multi-agent setup --name "My Mac" --workspace ws_xxx
|
|
@@ -342,6 +348,31 @@ async function cmdConnect(apiUrl: string, config: Config) {
|
|
|
342
348
|
}
|
|
343
349
|
}
|
|
344
350
|
|
|
351
|
+
async function cmdConnectDetached(apiUrl: string) {
|
|
352
|
+
if (existsSync(PID_PATH)) {
|
|
353
|
+
const pid = Number(readFileSync(PID_PATH, 'utf8').trim());
|
|
354
|
+
if (pid && isRunning(pid)) {
|
|
355
|
+
console.log(`❌ Daemon already running (pid ${pid}).`);
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
ensureDirs();
|
|
360
|
+
const logFd = Bun.file(LOG_PATH);
|
|
361
|
+
// Re-exec ourselves with same args minus --detach
|
|
362
|
+
const args = Bun.argv.slice(1).filter(a => a !== '-d' && a !== '--detach');
|
|
363
|
+
const proc = Bun.spawn([process.execPath, ...args, '--api', apiUrl], {
|
|
364
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
365
|
+
env: { ...process.env, MULTI_DETACHED: '1' },
|
|
366
|
+
});
|
|
367
|
+
(proc as any).unref?.();
|
|
368
|
+
// Give daemon a moment to write pidfile
|
|
369
|
+
await sleep(500);
|
|
370
|
+
console.log(`✅ Daemon started in background (pid ${proc.pid}).`);
|
|
371
|
+
console.log(` Tail logs: multi-agent logs`);
|
|
372
|
+
console.log(` Stop: multi-agent stop`);
|
|
373
|
+
process.exit(0);
|
|
374
|
+
}
|
|
375
|
+
|
|
345
376
|
async function pickFreePort(): Promise<number> {
|
|
346
377
|
// Bind to 0, read assigned port, close immediately.
|
|
347
378
|
for (let i = 0; i < 10; i++) {
|
|
@@ -397,13 +428,16 @@ async function handleRunTask(apiUrl: string, deviceId: string, task: any, detect
|
|
|
397
428
|
let liveBody = '';
|
|
398
429
|
let hadError = false;
|
|
399
430
|
let hasAssistantText = false;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
431
|
+
let liveCommentPromise: Promise<void> | null = null;
|
|
432
|
+
|
|
433
|
+
const ensureLiveComment = (): Promise<void> => {
|
|
434
|
+
if (liveCommentId) return Promise.resolve();
|
|
435
|
+
if (!liveCommentPromise) {
|
|
436
|
+
liveCommentPromise = apiClient.post<any>(`${apiUrl}/api/issues/${issueId}/comments`, {
|
|
437
|
+
author_type: 'agent', author_id: task.agent_id, author_name: 'agent', body: '…',
|
|
438
|
+
}).then(res => { liveCommentId = res.data?.id; });
|
|
439
|
+
}
|
|
440
|
+
return liveCommentPromise;
|
|
407
441
|
};
|
|
408
442
|
const patchLive = async (body: string) => {
|
|
409
443
|
if (!liveCommentId) return;
|