junis 0.1.5 → 0.1.8
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/cli/index.js +86 -7
- package/dist/server/mcp.js +75 -0
- package/dist/server/stdio.js +75 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "junis",
|
|
34
|
-
version: "0.1.
|
|
34
|
+
version: "0.1.8",
|
|
35
35
|
description: "One-line device control for AI agents",
|
|
36
36
|
bin: {
|
|
37
37
|
junis: "dist/cli/index.js"
|
|
@@ -119,7 +119,8 @@ async function authenticate(deviceName, platform2, onBrowserOpen, onWaiting) {
|
|
|
119
119
|
body: JSON.stringify({ device_name: deviceName, platform: platform2 })
|
|
120
120
|
});
|
|
121
121
|
if (!startRes.ok) {
|
|
122
|
-
|
|
122
|
+
const body = await startRes.text().catch(() => "");
|
|
123
|
+
throw new Error(`Auth \uC2DC\uC791 \uC2E4\uD328: ${startRes.status} ${body}`);
|
|
123
124
|
}
|
|
124
125
|
const startData = await startRes.json();
|
|
125
126
|
const verificationUri = JUNIS_WEB ? startData.verification_uri.replace(/^https?:\/\/[^/]+/, JUNIS_WEB) : startData.verification_uri;
|
|
@@ -673,6 +674,7 @@ function platform() {
|
|
|
673
674
|
return "linux";
|
|
674
675
|
}
|
|
675
676
|
var DeviceTools = class {
|
|
677
|
+
screenRecordPid = null;
|
|
676
678
|
register(server) {
|
|
677
679
|
server.tool(
|
|
678
680
|
"screen_capture",
|
|
@@ -762,6 +764,80 @@ var DeviceTools = class {
|
|
|
762
764
|
return { content: [{ type: "text", text: "\uD074\uB9BD\uBCF4\uB4DC \uC800\uC7A5 \uC644\uB8CC" }] };
|
|
763
765
|
}
|
|
764
766
|
);
|
|
767
|
+
server.tool(
|
|
768
|
+
"screen_record",
|
|
769
|
+
"\uD654\uBA74 \uB179\uD654 \uC2DC\uC791/\uC911\uC9C0 (macOS: screencapture -v, \uAE30\uD0C0: ffmpeg)",
|
|
770
|
+
{
|
|
771
|
+
action: import_zod4.z.enum(["start", "stop"]).describe("start: \uB179\uD654 \uC2DC\uC791, stop: \uB179\uD654 \uC911\uC9C0"),
|
|
772
|
+
output_path: import_zod4.z.string().optional().describe("\uC800\uC7A5 \uACBD\uB85C (start \uC2DC \uC0AC\uC6A9, \uAE30\uBCF8: /tmp/junis_record_<timestamp>.mp4)")
|
|
773
|
+
},
|
|
774
|
+
async ({ action, output_path }) => {
|
|
775
|
+
const p = platform();
|
|
776
|
+
if (action === "start") {
|
|
777
|
+
if (this.screenRecordPid) {
|
|
778
|
+
return { content: [{ type: "text", text: "\uC774\uBBF8 \uB179\uD654 \uC911\uC785\uB2C8\uB2E4." }] };
|
|
779
|
+
}
|
|
780
|
+
const tmpPath = output_path ?? `/tmp/junis_record_${Date.now()}.mp4`;
|
|
781
|
+
const { spawn } = await import("child_process");
|
|
782
|
+
const cmd = p === "mac" ? ["screencapture", ["-v", tmpPath]] : ["ffmpeg", ["-f", p === "win" ? "gdigrab" : "x11grab", "-i", p === "win" ? "desktop" : ":0.0", tmpPath]];
|
|
783
|
+
const child = spawn(cmd[0], cmd[1], { detached: true, stdio: "ignore" });
|
|
784
|
+
child.unref();
|
|
785
|
+
this.screenRecordPid = child.pid ?? null;
|
|
786
|
+
return { content: [{ type: "text", text: `\uB179\uD654 \uC2DC\uC791\uB428. \uC800\uC7A5 \uACBD\uB85C: ${tmpPath} (PID: ${this.screenRecordPid})` }] };
|
|
787
|
+
} else {
|
|
788
|
+
if (!this.screenRecordPid) {
|
|
789
|
+
return { content: [{ type: "text", text: "\uD604\uC7AC \uB179\uD654 \uC911\uC774 \uC544\uB2D9\uB2C8\uB2E4." }] };
|
|
790
|
+
}
|
|
791
|
+
try {
|
|
792
|
+
process.kill(this.screenRecordPid, "SIGINT");
|
|
793
|
+
} catch {
|
|
794
|
+
}
|
|
795
|
+
this.screenRecordPid = null;
|
|
796
|
+
return { content: [{ type: "text", text: "\uB179\uD654 \uC911\uC9C0\uB428." }] };
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
);
|
|
800
|
+
server.tool(
|
|
801
|
+
"location_get",
|
|
802
|
+
"\uD604\uC7AC \uC704\uCE58 \uC870\uD68C (macOS: CoreLocation CLI, \uAE30\uD0C0: IP \uAE30\uBC18 fallback)",
|
|
803
|
+
{},
|
|
804
|
+
async () => {
|
|
805
|
+
const p = platform();
|
|
806
|
+
if (p === "mac") {
|
|
807
|
+
try {
|
|
808
|
+
const { stdout } = await execAsync3("CoreLocationCLI -once -format '%latitude,%longitude'", { timeout: 1e4 });
|
|
809
|
+
const [lat, lon] = stdout.trim().split(",");
|
|
810
|
+
return { content: [{ type: "text", text: `\uC704\uB3C4: ${lat}, \uACBD\uB3C4: ${lon}` }] };
|
|
811
|
+
} catch {
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
const res = await fetch("https://ipapi.co/json/");
|
|
815
|
+
const data = await res.json();
|
|
816
|
+
return {
|
|
817
|
+
content: [{
|
|
818
|
+
type: "text",
|
|
819
|
+
text: `\uC704\uB3C4: ${data.latitude}, \uACBD\uB3C4: ${data.longitude}, \uB3C4\uC2DC: ${data.city}, \uAD6D\uAC00: ${data.country_name} (IP \uAE30\uBC18 \uCD94\uC815)`
|
|
820
|
+
}]
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
);
|
|
824
|
+
server.tool(
|
|
825
|
+
"audio_play",
|
|
826
|
+
"\uC624\uB514\uC624 \uD30C\uC77C \uC7AC\uC0DD (macOS: afplay, \uAE30\uD0C0: ffplay)",
|
|
827
|
+
{
|
|
828
|
+
file_path: import_zod4.z.string().describe("\uC7AC\uC0DD\uD560 \uC624\uB514\uC624 \uD30C\uC77C \uACBD\uB85C")
|
|
829
|
+
},
|
|
830
|
+
async ({ file_path }) => {
|
|
831
|
+
const p = platform();
|
|
832
|
+
const cmd = {
|
|
833
|
+
mac: `afplay "${file_path}"`,
|
|
834
|
+
win: `ffplay -nodisp -autoexit "${file_path}"`,
|
|
835
|
+
linux: `ffplay -nodisp -autoexit "${file_path}"`
|
|
836
|
+
}[p];
|
|
837
|
+
await execAsync3(cmd);
|
|
838
|
+
return { content: [{ type: "text", text: `\uC7AC\uC0DD \uC644\uB8CC: ${file_path}` }] };
|
|
839
|
+
}
|
|
840
|
+
);
|
|
765
841
|
}
|
|
766
842
|
};
|
|
767
843
|
|
|
@@ -1040,9 +1116,11 @@ function getDeviceName() {
|
|
|
1040
1116
|
function printBanner() {
|
|
1041
1117
|
console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
1042
1118
|
console.log("\u2551 \u2551");
|
|
1043
|
-
|
|
1119
|
+
const versionLabel = `\u{1F99E} J U N I S v${version}`;
|
|
1120
|
+
const padding = " ".repeat(46 - 3 - versionLabel.length);
|
|
1121
|
+
console.log(`\u2551 ${versionLabel}${padding}\u2551`);
|
|
1044
1122
|
console.log("\u2551 \u2551");
|
|
1045
|
-
console.log("\u2551 Device Agent for AI Teams
|
|
1123
|
+
console.log("\u2551 Device Agent for AI Teams \u2551");
|
|
1046
1124
|
console.log("\u2551 \u2551");
|
|
1047
1125
|
console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
1048
1126
|
console.log("");
|
|
@@ -1118,13 +1196,14 @@ import_commander.program.command("start", { isDefault: true }).description("Juni
|
|
|
1118
1196
|
console.log(" \u25C9 Status ....................... \u{1F7E2} online");
|
|
1119
1197
|
console.log("");
|
|
1120
1198
|
if (authResult.agent_id) {
|
|
1199
|
+
const workspaceName = `${deviceName} Workspace`;
|
|
1121
1200
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1122
1201
|
console.log(" STEP 4 \xB7 Create AI Team");
|
|
1123
1202
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1124
|
-
console.log(
|
|
1203
|
+
console.log(` \u25C9 Workspace created ............ ${workspaceName}`);
|
|
1125
1204
|
console.log(` \u25C9 Agent created ................ ${authResult.agent_name}`);
|
|
1126
1205
|
console.log(` \u25C9 Device linked ................ ${deviceName} \u2192 ${authResult.agent_name}`);
|
|
1127
|
-
console.log(" \u25C9 Tools assigned ...............
|
|
1206
|
+
console.log(" \u25C9 Tools assigned ............... call_device_mcp, list_device_mcp_tools");
|
|
1128
1207
|
console.log("");
|
|
1129
1208
|
}
|
|
1130
1209
|
} else {
|
|
@@ -1173,7 +1252,7 @@ import_commander.program.command("start", { isDefault: true }).description("Juni
|
|
|
1173
1252
|
console.log(` \u2192 ${webUrl}`);
|
|
1174
1253
|
console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
1175
1254
|
console.log("\u2502 \u2502");
|
|
1176
|
-
console.log("\u2502 Try asking your AI:
|
|
1255
|
+
console.log("\u2502 Try asking your AI: \u2502");
|
|
1177
1256
|
console.log("\u2502 \u2502");
|
|
1178
1257
|
console.log('\u2502 "\uB370\uC2A4\uD06C\uD1B1 \uD30C\uC77C \uBAA9\uB85D \uBCF4\uC5EC\uC918" \u2502');
|
|
1179
1258
|
console.log('\u2502 "\uD06C\uB86C\uC5D0\uC11C \uC624\uB298 \uB274\uC2A4 \uAC80\uC0C9\uD574\uC918" \u2502');
|
package/dist/server/mcp.js
CHANGED
|
@@ -446,6 +446,7 @@ function platform() {
|
|
|
446
446
|
return "linux";
|
|
447
447
|
}
|
|
448
448
|
var DeviceTools = class {
|
|
449
|
+
screenRecordPid = null;
|
|
449
450
|
register(server) {
|
|
450
451
|
server.tool(
|
|
451
452
|
"screen_capture",
|
|
@@ -535,6 +536,80 @@ var DeviceTools = class {
|
|
|
535
536
|
return { content: [{ type: "text", text: "\uD074\uB9BD\uBCF4\uB4DC \uC800\uC7A5 \uC644\uB8CC" }] };
|
|
536
537
|
}
|
|
537
538
|
);
|
|
539
|
+
server.tool(
|
|
540
|
+
"screen_record",
|
|
541
|
+
"\uD654\uBA74 \uB179\uD654 \uC2DC\uC791/\uC911\uC9C0 (macOS: screencapture -v, \uAE30\uD0C0: ffmpeg)",
|
|
542
|
+
{
|
|
543
|
+
action: import_zod4.z.enum(["start", "stop"]).describe("start: \uB179\uD654 \uC2DC\uC791, stop: \uB179\uD654 \uC911\uC9C0"),
|
|
544
|
+
output_path: import_zod4.z.string().optional().describe("\uC800\uC7A5 \uACBD\uB85C (start \uC2DC \uC0AC\uC6A9, \uAE30\uBCF8: /tmp/junis_record_<timestamp>.mp4)")
|
|
545
|
+
},
|
|
546
|
+
async ({ action, output_path }) => {
|
|
547
|
+
const p = platform();
|
|
548
|
+
if (action === "start") {
|
|
549
|
+
if (this.screenRecordPid) {
|
|
550
|
+
return { content: [{ type: "text", text: "\uC774\uBBF8 \uB179\uD654 \uC911\uC785\uB2C8\uB2E4." }] };
|
|
551
|
+
}
|
|
552
|
+
const tmpPath = output_path ?? `/tmp/junis_record_${Date.now()}.mp4`;
|
|
553
|
+
const { spawn } = await import("child_process");
|
|
554
|
+
const cmd = p === "mac" ? ["screencapture", ["-v", tmpPath]] : ["ffmpeg", ["-f", p === "win" ? "gdigrab" : "x11grab", "-i", p === "win" ? "desktop" : ":0.0", tmpPath]];
|
|
555
|
+
const child = spawn(cmd[0], cmd[1], { detached: true, stdio: "ignore" });
|
|
556
|
+
child.unref();
|
|
557
|
+
this.screenRecordPid = child.pid ?? null;
|
|
558
|
+
return { content: [{ type: "text", text: `\uB179\uD654 \uC2DC\uC791\uB428. \uC800\uC7A5 \uACBD\uB85C: ${tmpPath} (PID: ${this.screenRecordPid})` }] };
|
|
559
|
+
} else {
|
|
560
|
+
if (!this.screenRecordPid) {
|
|
561
|
+
return { content: [{ type: "text", text: "\uD604\uC7AC \uB179\uD654 \uC911\uC774 \uC544\uB2D9\uB2C8\uB2E4." }] };
|
|
562
|
+
}
|
|
563
|
+
try {
|
|
564
|
+
process.kill(this.screenRecordPid, "SIGINT");
|
|
565
|
+
} catch {
|
|
566
|
+
}
|
|
567
|
+
this.screenRecordPid = null;
|
|
568
|
+
return { content: [{ type: "text", text: "\uB179\uD654 \uC911\uC9C0\uB428." }] };
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
);
|
|
572
|
+
server.tool(
|
|
573
|
+
"location_get",
|
|
574
|
+
"\uD604\uC7AC \uC704\uCE58 \uC870\uD68C (macOS: CoreLocation CLI, \uAE30\uD0C0: IP \uAE30\uBC18 fallback)",
|
|
575
|
+
{},
|
|
576
|
+
async () => {
|
|
577
|
+
const p = platform();
|
|
578
|
+
if (p === "mac") {
|
|
579
|
+
try {
|
|
580
|
+
const { stdout } = await execAsync3("CoreLocationCLI -once -format '%latitude,%longitude'", { timeout: 1e4 });
|
|
581
|
+
const [lat, lon] = stdout.trim().split(",");
|
|
582
|
+
return { content: [{ type: "text", text: `\uC704\uB3C4: ${lat}, \uACBD\uB3C4: ${lon}` }] };
|
|
583
|
+
} catch {
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
const res = await fetch("https://ipapi.co/json/");
|
|
587
|
+
const data = await res.json();
|
|
588
|
+
return {
|
|
589
|
+
content: [{
|
|
590
|
+
type: "text",
|
|
591
|
+
text: `\uC704\uB3C4: ${data.latitude}, \uACBD\uB3C4: ${data.longitude}, \uB3C4\uC2DC: ${data.city}, \uAD6D\uAC00: ${data.country_name} (IP \uAE30\uBC18 \uCD94\uC815)`
|
|
592
|
+
}]
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
server.tool(
|
|
597
|
+
"audio_play",
|
|
598
|
+
"\uC624\uB514\uC624 \uD30C\uC77C \uC7AC\uC0DD (macOS: afplay, \uAE30\uD0C0: ffplay)",
|
|
599
|
+
{
|
|
600
|
+
file_path: import_zod4.z.string().describe("\uC7AC\uC0DD\uD560 \uC624\uB514\uC624 \uD30C\uC77C \uACBD\uB85C")
|
|
601
|
+
},
|
|
602
|
+
async ({ file_path }) => {
|
|
603
|
+
const p = platform();
|
|
604
|
+
const cmd = {
|
|
605
|
+
mac: `afplay "${file_path}"`,
|
|
606
|
+
win: `ffplay -nodisp -autoexit "${file_path}"`,
|
|
607
|
+
linux: `ffplay -nodisp -autoexit "${file_path}"`
|
|
608
|
+
}[p];
|
|
609
|
+
await execAsync3(cmd);
|
|
610
|
+
return { content: [{ type: "text", text: `\uC7AC\uC0DD \uC644\uB8CC: ${file_path}` }] };
|
|
611
|
+
}
|
|
612
|
+
);
|
|
538
613
|
}
|
|
539
614
|
};
|
|
540
615
|
|
package/dist/server/stdio.js
CHANGED
|
@@ -435,6 +435,7 @@ function platform() {
|
|
|
435
435
|
return "linux";
|
|
436
436
|
}
|
|
437
437
|
var DeviceTools = class {
|
|
438
|
+
screenRecordPid = null;
|
|
438
439
|
register(server) {
|
|
439
440
|
server.tool(
|
|
440
441
|
"screen_capture",
|
|
@@ -524,6 +525,80 @@ var DeviceTools = class {
|
|
|
524
525
|
return { content: [{ type: "text", text: "\uD074\uB9BD\uBCF4\uB4DC \uC800\uC7A5 \uC644\uB8CC" }] };
|
|
525
526
|
}
|
|
526
527
|
);
|
|
528
|
+
server.tool(
|
|
529
|
+
"screen_record",
|
|
530
|
+
"\uD654\uBA74 \uB179\uD654 \uC2DC\uC791/\uC911\uC9C0 (macOS: screencapture -v, \uAE30\uD0C0: ffmpeg)",
|
|
531
|
+
{
|
|
532
|
+
action: import_zod4.z.enum(["start", "stop"]).describe("start: \uB179\uD654 \uC2DC\uC791, stop: \uB179\uD654 \uC911\uC9C0"),
|
|
533
|
+
output_path: import_zod4.z.string().optional().describe("\uC800\uC7A5 \uACBD\uB85C (start \uC2DC \uC0AC\uC6A9, \uAE30\uBCF8: /tmp/junis_record_<timestamp>.mp4)")
|
|
534
|
+
},
|
|
535
|
+
async ({ action, output_path }) => {
|
|
536
|
+
const p = platform();
|
|
537
|
+
if (action === "start") {
|
|
538
|
+
if (this.screenRecordPid) {
|
|
539
|
+
return { content: [{ type: "text", text: "\uC774\uBBF8 \uB179\uD654 \uC911\uC785\uB2C8\uB2E4." }] };
|
|
540
|
+
}
|
|
541
|
+
const tmpPath = output_path ?? `/tmp/junis_record_${Date.now()}.mp4`;
|
|
542
|
+
const { spawn } = await import("child_process");
|
|
543
|
+
const cmd = p === "mac" ? ["screencapture", ["-v", tmpPath]] : ["ffmpeg", ["-f", p === "win" ? "gdigrab" : "x11grab", "-i", p === "win" ? "desktop" : ":0.0", tmpPath]];
|
|
544
|
+
const child = spawn(cmd[0], cmd[1], { detached: true, stdio: "ignore" });
|
|
545
|
+
child.unref();
|
|
546
|
+
this.screenRecordPid = child.pid ?? null;
|
|
547
|
+
return { content: [{ type: "text", text: `\uB179\uD654 \uC2DC\uC791\uB428. \uC800\uC7A5 \uACBD\uB85C: ${tmpPath} (PID: ${this.screenRecordPid})` }] };
|
|
548
|
+
} else {
|
|
549
|
+
if (!this.screenRecordPid) {
|
|
550
|
+
return { content: [{ type: "text", text: "\uD604\uC7AC \uB179\uD654 \uC911\uC774 \uC544\uB2D9\uB2C8\uB2E4." }] };
|
|
551
|
+
}
|
|
552
|
+
try {
|
|
553
|
+
process.kill(this.screenRecordPid, "SIGINT");
|
|
554
|
+
} catch {
|
|
555
|
+
}
|
|
556
|
+
this.screenRecordPid = null;
|
|
557
|
+
return { content: [{ type: "text", text: "\uB179\uD654 \uC911\uC9C0\uB428." }] };
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
);
|
|
561
|
+
server.tool(
|
|
562
|
+
"location_get",
|
|
563
|
+
"\uD604\uC7AC \uC704\uCE58 \uC870\uD68C (macOS: CoreLocation CLI, \uAE30\uD0C0: IP \uAE30\uBC18 fallback)",
|
|
564
|
+
{},
|
|
565
|
+
async () => {
|
|
566
|
+
const p = platform();
|
|
567
|
+
if (p === "mac") {
|
|
568
|
+
try {
|
|
569
|
+
const { stdout } = await execAsync3("CoreLocationCLI -once -format '%latitude,%longitude'", { timeout: 1e4 });
|
|
570
|
+
const [lat, lon] = stdout.trim().split(",");
|
|
571
|
+
return { content: [{ type: "text", text: `\uC704\uB3C4: ${lat}, \uACBD\uB3C4: ${lon}` }] };
|
|
572
|
+
} catch {
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
const res = await fetch("https://ipapi.co/json/");
|
|
576
|
+
const data = await res.json();
|
|
577
|
+
return {
|
|
578
|
+
content: [{
|
|
579
|
+
type: "text",
|
|
580
|
+
text: `\uC704\uB3C4: ${data.latitude}, \uACBD\uB3C4: ${data.longitude}, \uB3C4\uC2DC: ${data.city}, \uAD6D\uAC00: ${data.country_name} (IP \uAE30\uBC18 \uCD94\uC815)`
|
|
581
|
+
}]
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
);
|
|
585
|
+
server.tool(
|
|
586
|
+
"audio_play",
|
|
587
|
+
"\uC624\uB514\uC624 \uD30C\uC77C \uC7AC\uC0DD (macOS: afplay, \uAE30\uD0C0: ffplay)",
|
|
588
|
+
{
|
|
589
|
+
file_path: import_zod4.z.string().describe("\uC7AC\uC0DD\uD560 \uC624\uB514\uC624 \uD30C\uC77C \uACBD\uB85C")
|
|
590
|
+
},
|
|
591
|
+
async ({ file_path }) => {
|
|
592
|
+
const p = platform();
|
|
593
|
+
const cmd = {
|
|
594
|
+
mac: `afplay "${file_path}"`,
|
|
595
|
+
win: `ffplay -nodisp -autoexit "${file_path}"`,
|
|
596
|
+
linux: `ffplay -nodisp -autoexit "${file_path}"`
|
|
597
|
+
}[p];
|
|
598
|
+
await execAsync3(cmd);
|
|
599
|
+
return { content: [{ type: "text", text: `\uC7AC\uC0DD \uC644\uB8CC: ${file_path}` }] };
|
|
600
|
+
}
|
|
601
|
+
);
|
|
527
602
|
}
|
|
528
603
|
};
|
|
529
604
|
|