junis 0.1.7 → 0.2.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/cli/index.js +99 -7
- package/dist/server/mcp.js +87 -0
- package/dist/server/stdio.js +87 -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.
|
|
34
|
+
version: "0.2.0",
|
|
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;
|
|
@@ -181,9 +182,11 @@ var RelayClient = class {
|
|
|
181
182
|
destroyed = false;
|
|
182
183
|
async connect() {
|
|
183
184
|
if (this.destroyed) return;
|
|
184
|
-
const url = `${JUNIS_WS}/ws/devices/${this.config.device_key}
|
|
185
|
+
const url = `${JUNIS_WS}/ws/devices/${this.config.device_key}`;
|
|
185
186
|
console.log(`\u{1F517} \uB9B4\uB808\uC774 \uC11C\uBC84 \uC5F0\uACB0 \uC911...`);
|
|
186
|
-
this.ws = new import_ws.default(url
|
|
187
|
+
this.ws = new import_ws.default(url, {
|
|
188
|
+
headers: { Authorization: `Bearer ${this.config.token}` }
|
|
189
|
+
});
|
|
187
190
|
this.ws.on("open", () => {
|
|
188
191
|
console.log("\u2705 \uB9B4\uB808\uC774 \uC11C\uBC84 \uC5F0\uACB0\uB428");
|
|
189
192
|
this.reconnectDelay = 1e3;
|
|
@@ -446,6 +449,46 @@ ${error.stderr ?? ""}`
|
|
|
446
449
|
};
|
|
447
450
|
}
|
|
448
451
|
);
|
|
452
|
+
server.tool(
|
|
453
|
+
"edit_block",
|
|
454
|
+
"\uD30C\uC77C\uC758 \uD2B9\uC815 \uD14D\uC2A4\uD2B8 \uBE14\uB85D\uC744 \uC0C8 \uD14D\uC2A4\uD2B8\uB85C \uAD50\uCCB4 (diff \uAE30\uBC18 \uBD80\uBD84 \uC218\uC815)",
|
|
455
|
+
{
|
|
456
|
+
path: import_zod.z.string().describe("\uD30C\uC77C \uACBD\uB85C"),
|
|
457
|
+
old_string: import_zod.z.string().describe("\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8 (\uC815\uD655\uD788 \uC77C\uCE58\uD574\uC57C \uD568)"),
|
|
458
|
+
new_string: import_zod.z.string().describe("\uC0C8 \uD14D\uC2A4\uD2B8"),
|
|
459
|
+
replace_all: import_zod.z.boolean().optional().default(false).describe("true\uBA74 \uBAA8\uB4E0 \uB9E4\uCE6D \uAD50\uCCB4, false\uBA74 \uCCAB \uBC88\uC9F8\uB9CC")
|
|
460
|
+
},
|
|
461
|
+
async ({ path: filePath, old_string, new_string, replace_all }) => {
|
|
462
|
+
const content = await import_promises.default.readFile(filePath, "utf-8");
|
|
463
|
+
if (!content.includes(old_string)) {
|
|
464
|
+
throw new Error(`old_string\uC744 \uD30C\uC77C\uC5D0\uC11C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${filePath}`);
|
|
465
|
+
}
|
|
466
|
+
let count = 0;
|
|
467
|
+
let pos = 0;
|
|
468
|
+
while ((pos = content.indexOf(old_string, pos)) !== -1) {
|
|
469
|
+
count++;
|
|
470
|
+
pos += old_string.length;
|
|
471
|
+
}
|
|
472
|
+
if (!replace_all && count > 1) {
|
|
473
|
+
throw new Error(
|
|
474
|
+
`\uB9E4\uCE6D\uC774 ${count}\uAC1C\uC785\uB2C8\uB2E4. replace_all\uC744 true\uB85C \uD558\uAC70\uB098 \uB354 \uB113\uC740 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uD3EC\uD568\uD558\uC138\uC694.`
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
let result;
|
|
478
|
+
let replaced;
|
|
479
|
+
if (replace_all) {
|
|
480
|
+
result = content.split(old_string).join(new_string);
|
|
481
|
+
replaced = count;
|
|
482
|
+
} else {
|
|
483
|
+
result = content.replace(old_string, new_string);
|
|
484
|
+
replaced = 1;
|
|
485
|
+
}
|
|
486
|
+
await import_promises.default.writeFile(filePath, result, "utf-8");
|
|
487
|
+
return {
|
|
488
|
+
content: [{ type: "text", text: `\uAD50\uCCB4 \uC644\uB8CC (${replaced}\uAC1C \uBCC0\uACBD\uB428)` }]
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
);
|
|
449
492
|
}
|
|
450
493
|
};
|
|
451
494
|
|
|
@@ -659,6 +702,53 @@ var NotebookTools = class {
|
|
|
659
702
|
throw new Error("jupyter\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC124\uCE58 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694: pip install jupyter");
|
|
660
703
|
}
|
|
661
704
|
);
|
|
705
|
+
server.tool(
|
|
706
|
+
"notebook_add_cell",
|
|
707
|
+
"\uB178\uD2B8\uBD81\uC5D0 \uC0C8 \uC140 \uCD94\uAC00",
|
|
708
|
+
{
|
|
709
|
+
path: import_zod3.z.string().describe(".ipynb \uD30C\uC77C \uACBD\uB85C"),
|
|
710
|
+
cell_type: import_zod3.z.enum(["code", "markdown"]).describe("\uC140 \uD0C0\uC785"),
|
|
711
|
+
source: import_zod3.z.string().describe("\uC140 \uC18C\uC2A4 \uB0B4\uC6A9"),
|
|
712
|
+
position: import_zod3.z.number().optional().describe("\uC0BD\uC785 \uC704\uCE58(0-based). \uC5C6\uC73C\uBA74 \uB9E8 \uB05D\uC5D0 \uCD94\uAC00")
|
|
713
|
+
},
|
|
714
|
+
async ({ path: filePath, cell_type: cellType, source, position }) => {
|
|
715
|
+
const nb = await readNotebook(filePath);
|
|
716
|
+
const newCell = {
|
|
717
|
+
cell_type: cellType,
|
|
718
|
+
source: source.split("\n").map((l, i, arr) => i < arr.length - 1 ? l + "\n" : l),
|
|
719
|
+
metadata: {},
|
|
720
|
+
outputs: cellType === "code" ? [] : void 0,
|
|
721
|
+
execution_count: cellType === "code" ? null : void 0
|
|
722
|
+
};
|
|
723
|
+
let actualIndex;
|
|
724
|
+
if (position === void 0 || position === null) {
|
|
725
|
+
nb.cells.push(newCell);
|
|
726
|
+
actualIndex = nb.cells.length - 1;
|
|
727
|
+
} else {
|
|
728
|
+
nb.cells.splice(position, 0, newCell);
|
|
729
|
+
actualIndex = position;
|
|
730
|
+
}
|
|
731
|
+
await writeNotebook(filePath, nb);
|
|
732
|
+
return { content: [{ type: "text", text: `\uC140 \uCD94\uAC00 \uC644\uB8CC (index: ${actualIndex})` }] };
|
|
733
|
+
}
|
|
734
|
+
);
|
|
735
|
+
server.tool(
|
|
736
|
+
"notebook_delete_cell",
|
|
737
|
+
"\uB178\uD2B8\uBD81 \uD2B9\uC815 \uC140 \uC0AD\uC81C",
|
|
738
|
+
{
|
|
739
|
+
path: import_zod3.z.string().describe(".ipynb \uD30C\uC77C \uACBD\uB85C"),
|
|
740
|
+
cell_index: import_zod3.z.number().describe("\uC0AD\uC81C\uD560 \uC140 \uC778\uB371\uC2A4 (0-based)")
|
|
741
|
+
},
|
|
742
|
+
async ({ path: filePath, cell_index }) => {
|
|
743
|
+
const nb = await readNotebook(filePath);
|
|
744
|
+
if (cell_index < 0 || cell_index >= nb.cells.length) {
|
|
745
|
+
throw new Error(`\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uC140 \uC778\uB371\uC2A4: ${cell_index}`);
|
|
746
|
+
}
|
|
747
|
+
nb.cells.splice(cell_index, 1);
|
|
748
|
+
await writeNotebook(filePath, nb);
|
|
749
|
+
return { content: [{ type: "text", text: `\uC140 \uC0AD\uC81C \uC644\uB8CC (index: ${cell_index})` }] };
|
|
750
|
+
}
|
|
751
|
+
);
|
|
662
752
|
}
|
|
663
753
|
};
|
|
664
754
|
|
|
@@ -1115,9 +1205,11 @@ function getDeviceName() {
|
|
|
1115
1205
|
function printBanner() {
|
|
1116
1206
|
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");
|
|
1117
1207
|
console.log("\u2551 \u2551");
|
|
1118
|
-
|
|
1208
|
+
const versionLabel = `\u{1F99E} J U N I S v${version}`;
|
|
1209
|
+
const padding = " ".repeat(46 - 3 - versionLabel.length);
|
|
1210
|
+
console.log(`\u2551 ${versionLabel}${padding}\u2551`);
|
|
1119
1211
|
console.log("\u2551 \u2551");
|
|
1120
|
-
console.log("\u2551 Device Agent for AI Teams
|
|
1212
|
+
console.log("\u2551 Device Agent for AI Teams \u2551");
|
|
1121
1213
|
console.log("\u2551 \u2551");
|
|
1122
1214
|
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");
|
|
1123
1215
|
console.log("");
|
|
@@ -1249,7 +1341,7 @@ import_commander.program.command("start", { isDefault: true }).description("Juni
|
|
|
1249
1341
|
console.log(` \u2192 ${webUrl}`);
|
|
1250
1342
|
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");
|
|
1251
1343
|
console.log("\u2502 \u2502");
|
|
1252
|
-
console.log("\u2502 Try asking your AI:
|
|
1344
|
+
console.log("\u2502 Try asking your AI: \u2502");
|
|
1253
1345
|
console.log("\u2502 \u2502");
|
|
1254
1346
|
console.log('\u2502 "\uB370\uC2A4\uD06C\uD1B1 \uD30C\uC77C \uBAA9\uB85D \uBCF4\uC5EC\uC918" \u2502');
|
|
1255
1347
|
console.log('\u2502 "\uD06C\uB86C\uC5D0\uC11C \uC624\uB298 \uB274\uC2A4 \uAC80\uC0C9\uD574\uC918" \u2502');
|
package/dist/server/mcp.js
CHANGED
|
@@ -219,6 +219,46 @@ ${error.stderr ?? ""}`
|
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
221
|
);
|
|
222
|
+
server.tool(
|
|
223
|
+
"edit_block",
|
|
224
|
+
"\uD30C\uC77C\uC758 \uD2B9\uC815 \uD14D\uC2A4\uD2B8 \uBE14\uB85D\uC744 \uC0C8 \uD14D\uC2A4\uD2B8\uB85C \uAD50\uCCB4 (diff \uAE30\uBC18 \uBD80\uBD84 \uC218\uC815)",
|
|
225
|
+
{
|
|
226
|
+
path: import_zod.z.string().describe("\uD30C\uC77C \uACBD\uB85C"),
|
|
227
|
+
old_string: import_zod.z.string().describe("\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8 (\uC815\uD655\uD788 \uC77C\uCE58\uD574\uC57C \uD568)"),
|
|
228
|
+
new_string: import_zod.z.string().describe("\uC0C8 \uD14D\uC2A4\uD2B8"),
|
|
229
|
+
replace_all: import_zod.z.boolean().optional().default(false).describe("true\uBA74 \uBAA8\uB4E0 \uB9E4\uCE6D \uAD50\uCCB4, false\uBA74 \uCCAB \uBC88\uC9F8\uB9CC")
|
|
230
|
+
},
|
|
231
|
+
async ({ path: filePath, old_string, new_string, replace_all }) => {
|
|
232
|
+
const content = await import_promises.default.readFile(filePath, "utf-8");
|
|
233
|
+
if (!content.includes(old_string)) {
|
|
234
|
+
throw new Error(`old_string\uC744 \uD30C\uC77C\uC5D0\uC11C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${filePath}`);
|
|
235
|
+
}
|
|
236
|
+
let count = 0;
|
|
237
|
+
let pos = 0;
|
|
238
|
+
while ((pos = content.indexOf(old_string, pos)) !== -1) {
|
|
239
|
+
count++;
|
|
240
|
+
pos += old_string.length;
|
|
241
|
+
}
|
|
242
|
+
if (!replace_all && count > 1) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
`\uB9E4\uCE6D\uC774 ${count}\uAC1C\uC785\uB2C8\uB2E4. replace_all\uC744 true\uB85C \uD558\uAC70\uB098 \uB354 \uB113\uC740 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uD3EC\uD568\uD558\uC138\uC694.`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
let result;
|
|
248
|
+
let replaced;
|
|
249
|
+
if (replace_all) {
|
|
250
|
+
result = content.split(old_string).join(new_string);
|
|
251
|
+
replaced = count;
|
|
252
|
+
} else {
|
|
253
|
+
result = content.replace(old_string, new_string);
|
|
254
|
+
replaced = 1;
|
|
255
|
+
}
|
|
256
|
+
await import_promises.default.writeFile(filePath, result, "utf-8");
|
|
257
|
+
return {
|
|
258
|
+
content: [{ type: "text", text: `\uAD50\uCCB4 \uC644\uB8CC (${replaced}\uAC1C \uBCC0\uACBD\uB428)` }]
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
);
|
|
222
262
|
}
|
|
223
263
|
};
|
|
224
264
|
|
|
@@ -432,6 +472,53 @@ var NotebookTools = class {
|
|
|
432
472
|
throw new Error("jupyter\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC124\uCE58 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694: pip install jupyter");
|
|
433
473
|
}
|
|
434
474
|
);
|
|
475
|
+
server.tool(
|
|
476
|
+
"notebook_add_cell",
|
|
477
|
+
"\uB178\uD2B8\uBD81\uC5D0 \uC0C8 \uC140 \uCD94\uAC00",
|
|
478
|
+
{
|
|
479
|
+
path: import_zod3.z.string().describe(".ipynb \uD30C\uC77C \uACBD\uB85C"),
|
|
480
|
+
cell_type: import_zod3.z.enum(["code", "markdown"]).describe("\uC140 \uD0C0\uC785"),
|
|
481
|
+
source: import_zod3.z.string().describe("\uC140 \uC18C\uC2A4 \uB0B4\uC6A9"),
|
|
482
|
+
position: import_zod3.z.number().optional().describe("\uC0BD\uC785 \uC704\uCE58(0-based). \uC5C6\uC73C\uBA74 \uB9E8 \uB05D\uC5D0 \uCD94\uAC00")
|
|
483
|
+
},
|
|
484
|
+
async ({ path: filePath, cell_type: cellType, source, position }) => {
|
|
485
|
+
const nb = await readNotebook(filePath);
|
|
486
|
+
const newCell = {
|
|
487
|
+
cell_type: cellType,
|
|
488
|
+
source: source.split("\n").map((l, i, arr) => i < arr.length - 1 ? l + "\n" : l),
|
|
489
|
+
metadata: {},
|
|
490
|
+
outputs: cellType === "code" ? [] : void 0,
|
|
491
|
+
execution_count: cellType === "code" ? null : void 0
|
|
492
|
+
};
|
|
493
|
+
let actualIndex;
|
|
494
|
+
if (position === void 0 || position === null) {
|
|
495
|
+
nb.cells.push(newCell);
|
|
496
|
+
actualIndex = nb.cells.length - 1;
|
|
497
|
+
} else {
|
|
498
|
+
nb.cells.splice(position, 0, newCell);
|
|
499
|
+
actualIndex = position;
|
|
500
|
+
}
|
|
501
|
+
await writeNotebook(filePath, nb);
|
|
502
|
+
return { content: [{ type: "text", text: `\uC140 \uCD94\uAC00 \uC644\uB8CC (index: ${actualIndex})` }] };
|
|
503
|
+
}
|
|
504
|
+
);
|
|
505
|
+
server.tool(
|
|
506
|
+
"notebook_delete_cell",
|
|
507
|
+
"\uB178\uD2B8\uBD81 \uD2B9\uC815 \uC140 \uC0AD\uC81C",
|
|
508
|
+
{
|
|
509
|
+
path: import_zod3.z.string().describe(".ipynb \uD30C\uC77C \uACBD\uB85C"),
|
|
510
|
+
cell_index: import_zod3.z.number().describe("\uC0AD\uC81C\uD560 \uC140 \uC778\uB371\uC2A4 (0-based)")
|
|
511
|
+
},
|
|
512
|
+
async ({ path: filePath, cell_index }) => {
|
|
513
|
+
const nb = await readNotebook(filePath);
|
|
514
|
+
if (cell_index < 0 || cell_index >= nb.cells.length) {
|
|
515
|
+
throw new Error(`\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uC140 \uC778\uB371\uC2A4: ${cell_index}`);
|
|
516
|
+
}
|
|
517
|
+
nb.cells.splice(cell_index, 1);
|
|
518
|
+
await writeNotebook(filePath, nb);
|
|
519
|
+
return { content: [{ type: "text", text: `\uC140 \uC0AD\uC81C \uC644\uB8CC (index: ${cell_index})` }] };
|
|
520
|
+
}
|
|
521
|
+
);
|
|
435
522
|
}
|
|
436
523
|
};
|
|
437
524
|
|
package/dist/server/stdio.js
CHANGED
|
@@ -208,6 +208,46 @@ ${error.stderr ?? ""}`
|
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
210
|
);
|
|
211
|
+
server.tool(
|
|
212
|
+
"edit_block",
|
|
213
|
+
"\uD30C\uC77C\uC758 \uD2B9\uC815 \uD14D\uC2A4\uD2B8 \uBE14\uB85D\uC744 \uC0C8 \uD14D\uC2A4\uD2B8\uB85C \uAD50\uCCB4 (diff \uAE30\uBC18 \uBD80\uBD84 \uC218\uC815)",
|
|
214
|
+
{
|
|
215
|
+
path: import_zod.z.string().describe("\uD30C\uC77C \uACBD\uB85C"),
|
|
216
|
+
old_string: import_zod.z.string().describe("\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8 (\uC815\uD655\uD788 \uC77C\uCE58\uD574\uC57C \uD568)"),
|
|
217
|
+
new_string: import_zod.z.string().describe("\uC0C8 \uD14D\uC2A4\uD2B8"),
|
|
218
|
+
replace_all: import_zod.z.boolean().optional().default(false).describe("true\uBA74 \uBAA8\uB4E0 \uB9E4\uCE6D \uAD50\uCCB4, false\uBA74 \uCCAB \uBC88\uC9F8\uB9CC")
|
|
219
|
+
},
|
|
220
|
+
async ({ path: filePath, old_string, new_string, replace_all }) => {
|
|
221
|
+
const content = await import_promises.default.readFile(filePath, "utf-8");
|
|
222
|
+
if (!content.includes(old_string)) {
|
|
223
|
+
throw new Error(`old_string\uC744 \uD30C\uC77C\uC5D0\uC11C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${filePath}`);
|
|
224
|
+
}
|
|
225
|
+
let count = 0;
|
|
226
|
+
let pos = 0;
|
|
227
|
+
while ((pos = content.indexOf(old_string, pos)) !== -1) {
|
|
228
|
+
count++;
|
|
229
|
+
pos += old_string.length;
|
|
230
|
+
}
|
|
231
|
+
if (!replace_all && count > 1) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
`\uB9E4\uCE6D\uC774 ${count}\uAC1C\uC785\uB2C8\uB2E4. replace_all\uC744 true\uB85C \uD558\uAC70\uB098 \uB354 \uB113\uC740 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uD3EC\uD568\uD558\uC138\uC694.`
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
let result;
|
|
237
|
+
let replaced;
|
|
238
|
+
if (replace_all) {
|
|
239
|
+
result = content.split(old_string).join(new_string);
|
|
240
|
+
replaced = count;
|
|
241
|
+
} else {
|
|
242
|
+
result = content.replace(old_string, new_string);
|
|
243
|
+
replaced = 1;
|
|
244
|
+
}
|
|
245
|
+
await import_promises.default.writeFile(filePath, result, "utf-8");
|
|
246
|
+
return {
|
|
247
|
+
content: [{ type: "text", text: `\uAD50\uCCB4 \uC644\uB8CC (${replaced}\uAC1C \uBCC0\uACBD\uB428)` }]
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
);
|
|
211
251
|
}
|
|
212
252
|
};
|
|
213
253
|
|
|
@@ -421,6 +461,53 @@ var NotebookTools = class {
|
|
|
421
461
|
throw new Error("jupyter\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC124\uCE58 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694: pip install jupyter");
|
|
422
462
|
}
|
|
423
463
|
);
|
|
464
|
+
server.tool(
|
|
465
|
+
"notebook_add_cell",
|
|
466
|
+
"\uB178\uD2B8\uBD81\uC5D0 \uC0C8 \uC140 \uCD94\uAC00",
|
|
467
|
+
{
|
|
468
|
+
path: import_zod3.z.string().describe(".ipynb \uD30C\uC77C \uACBD\uB85C"),
|
|
469
|
+
cell_type: import_zod3.z.enum(["code", "markdown"]).describe("\uC140 \uD0C0\uC785"),
|
|
470
|
+
source: import_zod3.z.string().describe("\uC140 \uC18C\uC2A4 \uB0B4\uC6A9"),
|
|
471
|
+
position: import_zod3.z.number().optional().describe("\uC0BD\uC785 \uC704\uCE58(0-based). \uC5C6\uC73C\uBA74 \uB9E8 \uB05D\uC5D0 \uCD94\uAC00")
|
|
472
|
+
},
|
|
473
|
+
async ({ path: filePath, cell_type: cellType, source, position }) => {
|
|
474
|
+
const nb = await readNotebook(filePath);
|
|
475
|
+
const newCell = {
|
|
476
|
+
cell_type: cellType,
|
|
477
|
+
source: source.split("\n").map((l, i, arr) => i < arr.length - 1 ? l + "\n" : l),
|
|
478
|
+
metadata: {},
|
|
479
|
+
outputs: cellType === "code" ? [] : void 0,
|
|
480
|
+
execution_count: cellType === "code" ? null : void 0
|
|
481
|
+
};
|
|
482
|
+
let actualIndex;
|
|
483
|
+
if (position === void 0 || position === null) {
|
|
484
|
+
nb.cells.push(newCell);
|
|
485
|
+
actualIndex = nb.cells.length - 1;
|
|
486
|
+
} else {
|
|
487
|
+
nb.cells.splice(position, 0, newCell);
|
|
488
|
+
actualIndex = position;
|
|
489
|
+
}
|
|
490
|
+
await writeNotebook(filePath, nb);
|
|
491
|
+
return { content: [{ type: "text", text: `\uC140 \uCD94\uAC00 \uC644\uB8CC (index: ${actualIndex})` }] };
|
|
492
|
+
}
|
|
493
|
+
);
|
|
494
|
+
server.tool(
|
|
495
|
+
"notebook_delete_cell",
|
|
496
|
+
"\uB178\uD2B8\uBD81 \uD2B9\uC815 \uC140 \uC0AD\uC81C",
|
|
497
|
+
{
|
|
498
|
+
path: import_zod3.z.string().describe(".ipynb \uD30C\uC77C \uACBD\uB85C"),
|
|
499
|
+
cell_index: import_zod3.z.number().describe("\uC0AD\uC81C\uD560 \uC140 \uC778\uB371\uC2A4 (0-based)")
|
|
500
|
+
},
|
|
501
|
+
async ({ path: filePath, cell_index }) => {
|
|
502
|
+
const nb = await readNotebook(filePath);
|
|
503
|
+
if (cell_index < 0 || cell_index >= nb.cells.length) {
|
|
504
|
+
throw new Error(`\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uC140 \uC778\uB371\uC2A4: ${cell_index}`);
|
|
505
|
+
}
|
|
506
|
+
nb.cells.splice(cell_index, 1);
|
|
507
|
+
await writeNotebook(filePath, nb);
|
|
508
|
+
return { content: [{ type: "text", text: `\uC140 \uC0AD\uC81C \uC644\uB8CC (index: ${cell_index})` }] };
|
|
509
|
+
}
|
|
510
|
+
);
|
|
424
511
|
}
|
|
425
512
|
};
|
|
426
513
|
|