gemini-studio-mcp 0.1.0 → 0.3.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/README.md +11 -4
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/cost/pricing.js +31 -0
- package/dist/cost/pricing.js.map +1 -0
- package/dist/gemini/client.js +9 -0
- package/dist/gemini/client.js.map +1 -1
- package/dist/server.js +7 -1
- package/dist/server.js.map +1 -1
- package/dist/store/presetStore.js +34 -0
- package/dist/store/presetStore.js.map +1 -0
- package/dist/tools/editImage.js +10 -6
- package/dist/tools/editImage.js.map +1 -1
- package/dist/tools/gallery.js +38 -0
- package/dist/tools/gallery.js.map +1 -0
- package/dist/tools/generateImage.js +18 -6
- package/dist/tools/generateImage.js.map +1 -1
- package/dist/tools/generateVideo.js +15 -7
- package/dist/tools/generateVideo.js.map +1 -1
- package/dist/tools/presets.js +28 -0
- package/dist/tools/presets.js.map +1 -0
- package/dist/tools/translate.js +12 -0
- package/dist/tools/translate.js.map +1 -0
- package/dist/translate/detect.js +6 -0
- package/dist/translate/detect.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,6 +68,8 @@ Get a key at **https://aistudio.google.com/apikey** — then restart your client
|
|
|
68
68
|
| `edit_image` | Edit a stored image by `id` with a text instruction. |
|
|
69
69
|
| `iterate` | Refine the **last** (or a given) image in words — _"warmer", "different angle", "same character"_. |
|
|
70
70
|
| `generate_video` | Text → video (Veo). v1 waits for the render to finish. |
|
|
71
|
+
| `save_preset` / `list_presets` | Save and reuse named style presets. |
|
|
72
|
+
| `gallery` / `show_asset` | Browse past generations by metadata and re-open any by id. |
|
|
71
73
|
|
|
72
74
|
### Example conversation
|
|
73
75
|
|
|
@@ -86,10 +88,14 @@ Get a key at **https://aistudio.google.com/apikey** — then restart your client
|
|
|
86
88
|
| `GEMINI_IMAGE_MODEL` | Image generation model | `imagen-4.0-generate-001` |
|
|
87
89
|
| `GEMINI_EDIT_MODEL` | Edit / iterate model | `gemini-3-pro-image-preview` |
|
|
88
90
|
| `GEMINI_VIDEO_MODEL` | Video model | `veo-3.1-generate-preview` |
|
|
91
|
+
| `GEMINI_AUTO_TRANSLATE` | Auto-translate non-English prompts | `true` |
|
|
92
|
+
| `GEMINI_TRANSLATE_MODEL` | Model used for translation | `gemini-2.5-flash` |
|
|
93
|
+
|
|
94
|
+
**Cost awareness:** image tools report an estimated price; `generate_video` is paid and returns an estimate first — pass `confirm: true` to actually render.
|
|
89
95
|
|
|
90
96
|
> **Tip:** when launched via `npx` from a desktop client, the process working directory may be non-obvious — set `GEMINI_STUDIO_DIR` to an absolute path so you can always find your output.
|
|
91
97
|
|
|
92
|
-
> **
|
|
98
|
+
> **Multilingual:** non-English prompts are auto-translated to English before generation (Imagen follows English best). Disable per call with `translate: false`, or globally with `GEMINI_AUTO_TRANSLATE=false`.
|
|
93
99
|
|
|
94
100
|
## How it works
|
|
95
101
|
|
|
@@ -116,9 +122,10 @@ Tested against the live Gemini API: ✅ `generate_image` (Imagen 4) · ✅ `edit
|
|
|
116
122
|
|
|
117
123
|
## Roadmap
|
|
118
124
|
|
|
119
|
-
- **
|
|
120
|
-
- **
|
|
121
|
-
- **
|
|
125
|
+
- **v0.1 — core:** generate · edit · iterate · video, with asset lineage.
|
|
126
|
+
- **v0.2 — studio:** style presets, gallery & `show_asset`, cost estimates (with a `confirm` gate on paid video).
|
|
127
|
+
- **v0.3 — multilingual (current):** non-English prompts auto-translated to English for better adherence.
|
|
128
|
+
- **Next:** non-blocking / resumable video jobs with progress.
|
|
122
129
|
|
|
123
130
|
## Development
|
|
124
131
|
|
package/dist/config.js
CHANGED
|
@@ -14,6 +14,8 @@ export function loadConfig(env = process.env) {
|
|
|
14
14
|
defaultImageModel: env.GEMINI_IMAGE_MODEL ?? 'imagen-4.0-generate-001',
|
|
15
15
|
editModel: env.GEMINI_EDIT_MODEL ?? 'gemini-3-pro-image-preview',
|
|
16
16
|
videoModel: env.GEMINI_VIDEO_MODEL ?? 'veo-3.1-generate-preview',
|
|
17
|
+
autoTranslate: env.GEMINI_AUTO_TRANSLATE !== 'false',
|
|
18
|
+
translateModel: env.GEMINI_TRANSLATE_MODEL ?? 'gemini-2.5-flash',
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAY7B,MAAM,OAAO,kBAAmB,SAAQ,KAAK;CAAG;AAEhD,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,MAAM,GAAG,GAAG,CAAC,cAAc,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,kBAAkB,CAC1B,6EAA6E;YAC7E,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAClG,OAAO;QACL,MAAM;QACN,UAAU,EAAE,OAAO;QACnB,iBAAiB,EAAE,GAAG,CAAC,kBAAkB,IAAI,yBAAyB;QACtE,SAAS,EAAE,GAAG,CAAC,iBAAiB,IAAI,4BAA4B;QAChE,UAAU,EAAE,GAAG,CAAC,kBAAkB,IAAI,0BAA0B;QAChE,aAAa,EAAE,GAAG,CAAC,qBAAqB,KAAK,OAAO;QACpD,cAAc,EAAE,GAAG,CAAC,sBAAsB,IAAI,kBAAkB;KACjE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Приблизительные тарифы, на 2026-05. Источники: ai.google.dev/gemini-api/docs/pricing.
|
|
2
|
+
const IMAGE_USD = {
|
|
3
|
+
'imagen-4.0-generate-001': 0.04,
|
|
4
|
+
'gemini-3-pro-image-preview': 0.06,
|
|
5
|
+
};
|
|
6
|
+
const VIDEO_USD_PER_SEC = {
|
|
7
|
+
'veo-3.1-generate-preview': 0.4,
|
|
8
|
+
};
|
|
9
|
+
const DEFAULT_VIDEO_SECONDS = 8;
|
|
10
|
+
function fmt(usd) {
|
|
11
|
+
return `$${usd.toFixed(2)}`;
|
|
12
|
+
}
|
|
13
|
+
export function estimateCost(opts) {
|
|
14
|
+
if (opts.kind === 'image') {
|
|
15
|
+
const per = IMAGE_USD[opts.model];
|
|
16
|
+
const count = opts.count ?? 1;
|
|
17
|
+
if (per === undefined) {
|
|
18
|
+
return { usd: 0, text: `стоимость неизвестна для модели ${opts.model}` };
|
|
19
|
+
}
|
|
20
|
+
const usd = per * count;
|
|
21
|
+
return { usd, text: `~${fmt(usd)} (${count} × ${fmt(per)})` };
|
|
22
|
+
}
|
|
23
|
+
const perSec = VIDEO_USD_PER_SEC[opts.model];
|
|
24
|
+
const seconds = opts.seconds ?? DEFAULT_VIDEO_SECONDS;
|
|
25
|
+
if (perSec === undefined) {
|
|
26
|
+
return { usd: 0, text: `стоимость неизвестна для модели ${opts.model}` };
|
|
27
|
+
}
|
|
28
|
+
const usd = perSec * seconds;
|
|
29
|
+
return { usd, text: `~${fmt(usd)} (${seconds}s × ${fmt(perSec)}/s)` };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/cost/pricing.ts"],"names":[],"mappings":"AAKA,wFAAwF;AACxF,MAAM,SAAS,GAA2B;IACxC,yBAAyB,EAAE,IAAI;IAC/B,4BAA4B,EAAE,IAAI;CACnC,CAAC;AACF,MAAM,iBAAiB,GAA2B;IAChD,0BAA0B,EAAE,GAAG;CAChC,CAAC;AACF,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEhC,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAK5B;IACC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAC9B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,mCAAmC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAC3E,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC;QACxB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,qBAAqB,CAAC;IACtD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,mCAAmC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;IAC3E,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,OAAO,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;AACxE,CAAC"}
|
package/dist/gemini/client.js
CHANGED
|
@@ -18,6 +18,15 @@ export class RealGeminiClient {
|
|
|
18
18
|
}
|
|
19
19
|
return { data: Buffer.from(img.imageBytes, 'base64'), mimeType: img.mimeType ?? 'image/png' };
|
|
20
20
|
}
|
|
21
|
+
async translateToEnglish(text, model) {
|
|
22
|
+
const res = await this.ai.models.generateContent({
|
|
23
|
+
model,
|
|
24
|
+
contents: 'Translate the following image prompt to natural English. ' +
|
|
25
|
+
'Output ONLY the translation — no quotes, no notes, no preamble:\n\n' + text,
|
|
26
|
+
});
|
|
27
|
+
const out = (res?.text ?? '').trim();
|
|
28
|
+
return out || text;
|
|
29
|
+
}
|
|
21
30
|
async editImage({ prompt, model, image }) {
|
|
22
31
|
const res = await this.ai.interactions.create({
|
|
23
32
|
model,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gemini/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gemini/client.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -4,25 +4,31 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
4
4
|
import { loadConfig } from './config.js';
|
|
5
5
|
import { RealGeminiClient } from './gemini/client.js';
|
|
6
6
|
import { AssetStore } from './store/assetStore.js';
|
|
7
|
+
import { PresetStore } from './store/presetStore.js';
|
|
7
8
|
import { Session } from './session/session.js';
|
|
8
9
|
import { registerGenerateImage } from './tools/generateImage.js';
|
|
9
10
|
import { registerEditImage } from './tools/editImage.js';
|
|
10
11
|
import { registerIterate } from './tools/iterate.js';
|
|
11
12
|
import { registerGenerateVideo } from './tools/generateVideo.js';
|
|
13
|
+
import { registerPresetTools } from './tools/presets.js';
|
|
14
|
+
import { registerGalleryTools } from './tools/gallery.js';
|
|
12
15
|
export async function startServer() {
|
|
13
16
|
const config = loadConfig();
|
|
14
17
|
const ai = new GoogleGenAI({ apiKey: config.apiKey });
|
|
15
18
|
const deps = {
|
|
16
19
|
client: new RealGeminiClient(ai),
|
|
17
20
|
store: new AssetStore(config.workingDir),
|
|
21
|
+
presets: new PresetStore(config.workingDir),
|
|
18
22
|
session: new Session(),
|
|
19
23
|
config,
|
|
20
24
|
};
|
|
21
|
-
const server = new McpServer({ name: 'gemini-studio-mcp', version: '0.
|
|
25
|
+
const server = new McpServer({ name: 'gemini-studio-mcp', version: '0.3.0' });
|
|
22
26
|
registerGenerateImage(server, deps);
|
|
23
27
|
registerEditImage(server, deps);
|
|
24
28
|
registerIterate(server, deps);
|
|
25
29
|
registerGenerateVideo(server, deps);
|
|
30
|
+
registerPresetTools(server, deps);
|
|
31
|
+
registerGalleryTools(server, deps);
|
|
26
32
|
const transport = new StdioServerTransport();
|
|
27
33
|
await server.connect(transport);
|
|
28
34
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,EAAE,GAAG,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,MAAM,IAAI,GAAa;QACrB,MAAM,EAAE,IAAI,gBAAgB,CAAC,EAAS,CAAC;QACvC,KAAK,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC;QACxC,OAAO,EAAE,IAAI,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC;QAC3C,OAAO,EAAE,IAAI,OAAO,EAAE;QACtB,MAAM;KACP,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9B,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEnC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export class PresetStore {
|
|
4
|
+
rootDir;
|
|
5
|
+
queue = Promise.resolve();
|
|
6
|
+
constructor(rootDir) {
|
|
7
|
+
this.rootDir = rootDir;
|
|
8
|
+
}
|
|
9
|
+
file() { return path.join(this.rootDir, 'presets.json'); }
|
|
10
|
+
async list() {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(await fs.readFile(this.file(), 'utf8'));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async get(name) {
|
|
19
|
+
const found = (await this.list()).find((p) => p.name === name);
|
|
20
|
+
return found ?? null;
|
|
21
|
+
}
|
|
22
|
+
save(preset) {
|
|
23
|
+
const run = this.queue.then(() => this.doSave(preset));
|
|
24
|
+
this.queue = run.catch(() => { });
|
|
25
|
+
return run;
|
|
26
|
+
}
|
|
27
|
+
async doSave(preset) {
|
|
28
|
+
await fs.mkdir(this.rootDir, { recursive: true });
|
|
29
|
+
const list = await this.list();
|
|
30
|
+
const next = [...list.filter((p) => p.name !== preset.name), preset];
|
|
31
|
+
await fs.writeFile(this.file(), JSON.stringify(next, null, 2));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=presetStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presetStore.js","sourceRoot":"","sources":["../../src/store/presetStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,MAAM,OAAO,WAAW;IAEO;IADrB,KAAK,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IACjD,YAA6B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;IAExC,IAAI,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAE1E,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAa,CAAC;QACxE,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,EAAE,CAAC;QAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY;QACpB,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC/D,OAAO,KAAK,IAAI,IAAI,CAAC;IACvB,CAAC;IAED,IAAI,CAAC,MAAc;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjC,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,MAAc;QACjC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;CACF"}
|
package/dist/tools/editImage.js
CHANGED
|
@@ -2,10 +2,13 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { imageResult, errorResult } from './result.js';
|
|
4
4
|
import { extFromMime } from '../util/mime.js';
|
|
5
|
+
import { estimateCost } from '../cost/pricing.js';
|
|
6
|
+
import { maybeTranslate } from './translate.js';
|
|
5
7
|
export const editImageInput = {
|
|
6
8
|
id: z.string().describe('id ранее сгенерированного изображения'),
|
|
7
9
|
prompt: z.string().describe('Что изменить'),
|
|
8
10
|
model: z.string().optional(),
|
|
11
|
+
translate: z.boolean().optional().describe('Перевести инструкцию на английский (по умолчанию авто при кириллице)'),
|
|
9
12
|
};
|
|
10
13
|
export async function editImageHandler(input, deps) {
|
|
11
14
|
try {
|
|
@@ -13,27 +16,28 @@ export async function editImageHandler(input, deps) {
|
|
|
13
16
|
const bytes = await deps.store.readBytes(input.id);
|
|
14
17
|
if (!source || !bytes)
|
|
15
18
|
throw new Error(`Изображение с id="${input.id}" не найдено.`);
|
|
19
|
+
const t = await maybeTranslate(input.prompt, deps, input.translate);
|
|
16
20
|
const model = input.model ?? deps.config.editModel;
|
|
17
21
|
const media = await deps.client.editImage({
|
|
18
|
-
prompt:
|
|
22
|
+
prompt: t.text, model, image: { data: bytes, mimeType: source.mimeType },
|
|
19
23
|
});
|
|
20
24
|
const id = randomUUID().slice(0, 8);
|
|
21
25
|
const manifest = {
|
|
22
|
-
id, parentId: source.id, kind: 'image', prompt:
|
|
26
|
+
id, parentId: source.id, kind: 'image', prompt: t.text, model,
|
|
23
27
|
file: `${id}.${extFromMime(media.mimeType)}`, mimeType: media.mimeType,
|
|
24
28
|
createdAt: new Date().toISOString(),
|
|
25
29
|
};
|
|
26
30
|
await deps.store.save(manifest, media.data);
|
|
27
31
|
deps.session.setLastImageId(id);
|
|
28
|
-
|
|
32
|
+
const cost = estimateCost({ kind: 'image', model });
|
|
33
|
+
const note = t.translated ? ` Инструкция переведена: "${t.text}".` : '';
|
|
34
|
+
return imageResult(media, `Готово. id=${id} (правка ${source.id}), файл: ${manifest.file}. Стоимость: ${cost.text}.${note}`);
|
|
29
35
|
}
|
|
30
36
|
catch (err) {
|
|
31
37
|
return errorResult(err);
|
|
32
38
|
}
|
|
33
39
|
}
|
|
34
40
|
export function registerEditImage(server, deps) {
|
|
35
|
-
server.registerTool('edit_image', { title: 'Edit image', description: 'Отредактировать сохранённое изображение по его id и текстовой
|
|
36
|
-
// cast: handler returns our CallToolResult; SDK expects its own index-signature variant (runtime-compatible).
|
|
37
|
-
(input) => editImageHandler(input, deps));
|
|
41
|
+
server.registerTool('edit_image', { title: 'Edit image', description: 'Отредактировать сохранённое изображение по его id и текстовой инструкции (русская инструкция переводится автоматически).', inputSchema: editImageInput }, (input) => editImageHandler(input, deps));
|
|
38
42
|
}
|
|
39
43
|
//# sourceMappingURL=editImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editImage.js","sourceRoot":"","sources":["../../src/tools/editImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"editImage.js","sourceRoot":"","sources":["../../src/tools/editImage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { imageResult, errorResult } from './result.js';
|
|
3
|
+
export const galleryInput = {
|
|
4
|
+
limit: z.number().int().positive().optional().describe('Сколько последних показать (по умолчанию 20)'),
|
|
5
|
+
};
|
|
6
|
+
export async function galleryHandler(input, deps) {
|
|
7
|
+
const all = await deps.store.list();
|
|
8
|
+
if (all.length === 0) {
|
|
9
|
+
return { content: [{ type: 'text', text: 'Галерея пуста — ещё ничего не сгенерировано.' }] };
|
|
10
|
+
}
|
|
11
|
+
const sorted = [...all].sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
12
|
+
const limit = input.limit ?? 20;
|
|
13
|
+
const lines = sorted.slice(0, limit).map((m) => {
|
|
14
|
+
const parent = m.parentId ? ` ← ${m.parentId}` : '';
|
|
15
|
+
return `• ${m.id} [${m.kind}] "${m.prompt}" (${m.model})${parent} — ${m.createdAt}`;
|
|
16
|
+
});
|
|
17
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
18
|
+
}
|
|
19
|
+
export const showAssetInput = {
|
|
20
|
+
id: z.string().describe('id ассета из галереи'),
|
|
21
|
+
};
|
|
22
|
+
export async function showAssetHandler(input, deps) {
|
|
23
|
+
try {
|
|
24
|
+
const manifest = await deps.store.get(input.id);
|
|
25
|
+
const bytes = await deps.store.readBytes(input.id);
|
|
26
|
+
if (!manifest || !bytes)
|
|
27
|
+
throw new Error(`Ассет с id="${input.id}" не найден.`);
|
|
28
|
+
return imageResult({ data: bytes, mimeType: manifest.mimeType }, `${manifest.id} [${manifest.kind}] "${manifest.prompt}" — файл: ${manifest.file}`);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return errorResult(err);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function registerGalleryTools(server, deps) {
|
|
35
|
+
server.registerTool('gallery', { title: 'Gallery', description: 'Показать список прошлых генераций с метаданными (id, промпт, модель, родитель, дата).', inputSchema: galleryInput }, (input) => galleryHandler(input, deps));
|
|
36
|
+
server.registerTool('show_asset', { title: 'Show asset', description: 'Показать сохранённый ассет (изображение или видео) по его id.', inputSchema: showAssetInput }, (input) => showAssetHandler(input, deps));
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=gallery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/tools/gallery.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,31 +2,43 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { imageResult, errorResult } from './result.js';
|
|
4
4
|
import { extFromMime } from '../util/mime.js';
|
|
5
|
+
import { estimateCost } from '../cost/pricing.js';
|
|
6
|
+
import { maybeTranslate } from './translate.js';
|
|
5
7
|
export const generateImageInput = {
|
|
6
8
|
prompt: z.string().describe('Что нарисовать'),
|
|
7
9
|
model: z.string().optional().describe('Переопределить модель (по умолчанию Imagen 4)'),
|
|
10
|
+
preset: z.string().optional().describe('Имя сохранённого пресета стиля (его стиль добавится к промпту)'),
|
|
11
|
+
translate: z.boolean().optional().describe('Перевести промпт на английский (по умолчанию авто при кириллице)'),
|
|
8
12
|
};
|
|
9
13
|
export async function generateImageHandler(input, deps) {
|
|
10
14
|
try {
|
|
15
|
+
const t = await maybeTranslate(input.prompt, deps, input.translate);
|
|
16
|
+
let prompt = t.text;
|
|
17
|
+
if (input.preset) {
|
|
18
|
+
const preset = await deps.presets.get(input.preset);
|
|
19
|
+
if (!preset)
|
|
20
|
+
throw new Error(`Пресет "${input.preset}" не найден.`);
|
|
21
|
+
prompt = `${prompt}, ${preset.style}`;
|
|
22
|
+
}
|
|
11
23
|
const model = input.model ?? deps.config.defaultImageModel;
|
|
12
|
-
const media = await deps.client.generateImage({ prompt
|
|
24
|
+
const media = await deps.client.generateImage({ prompt, model });
|
|
13
25
|
const id = randomUUID().slice(0, 8);
|
|
14
26
|
const manifest = {
|
|
15
|
-
id, parentId: null, kind: 'image', prompt
|
|
27
|
+
id, parentId: null, kind: 'image', prompt, model,
|
|
16
28
|
file: `${id}.${extFromMime(media.mimeType)}`, mimeType: media.mimeType,
|
|
17
29
|
createdAt: new Date().toISOString(),
|
|
18
30
|
};
|
|
19
31
|
await deps.store.save(manifest, media.data);
|
|
20
32
|
deps.session.setLastImageId(id);
|
|
21
|
-
|
|
33
|
+
const cost = estimateCost({ kind: 'image', model });
|
|
34
|
+
const note = t.translated ? ` Промпт переведён на английский: "${t.text}".` : '';
|
|
35
|
+
return imageResult(media, `Готово. id=${id}, файл: ${manifest.file} (в ${deps.config.workingDir}). Стоимость: ${cost.text}.${note}`);
|
|
22
36
|
}
|
|
23
37
|
catch (err) {
|
|
24
38
|
return errorResult(err);
|
|
25
39
|
}
|
|
26
40
|
}
|
|
27
41
|
export function registerGenerateImage(server, deps) {
|
|
28
|
-
server.registerTool('generate_image', { title: 'Generate image', description: 'Сгенерировать изображение по тексту через Gemini (Imagen 4).', inputSchema: generateImageInput },
|
|
29
|
-
// cast: handler returns our CallToolResult; SDK expects its own index-signature variant (runtime-compatible).
|
|
30
|
-
(input) => generateImageHandler(input, deps));
|
|
42
|
+
server.registerTool('generate_image', { title: 'Generate image', description: 'Сгенерировать изображение по тексту через Gemini (Imagen 4). Русские промпты автоматически переводятся на английский. Можно указать preset.', inputSchema: generateImageInput }, (input) => generateImageHandler(input, deps));
|
|
31
43
|
}
|
|
32
44
|
//# sourceMappingURL=generateImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateImage.js","sourceRoot":"","sources":["../../src/tools/generateImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"generateImage.js","sourceRoot":"","sources":["../../src/tools/generateImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;IACtF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gEAAgE,CAAC;IACxG,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kEAAkE,CAAC;CAC/G,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAA+E,EAC/E,IAAc;IAEd,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACpE,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC;QACpB,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC,MAAM,cAAc,CAAC,CAAC;YACpE,MAAM,GAAG,GAAG,MAAM,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAC3D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACjE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAkB;YAC9B,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK;YAChD,IAAI,EAAE,GAAG,EAAE,IAAI,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACtE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QACF,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,OAAO,WAAW,CAAC,KAAK,EAAE,cAAc,EAAE,WAAW,QAAQ,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,iBAAiB,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;IACvI,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,IAAc;IACrE,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB,EAAE,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,6IAA6I,EAAE,WAAW,EAAE,kBAAkB,EAAE,EACxN,CAAC,KAAK,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAQ,CACpD,CAAC;AACJ,CAAC"}
|
|
@@ -2,30 +2,38 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { imageResult, errorResult } from './result.js';
|
|
4
4
|
import { extFromMime } from '../util/mime.js';
|
|
5
|
+
import { estimateCost } from '../cost/pricing.js';
|
|
6
|
+
import { maybeTranslate } from './translate.js';
|
|
5
7
|
export const generateVideoInput = {
|
|
6
8
|
prompt: z.string().describe('Что снять'),
|
|
7
9
|
model: z.string().optional(),
|
|
10
|
+
confirm: z.boolean().optional().describe('Подтверждение генерации видео (платно). Без него вернётся только смета.'),
|
|
11
|
+
translate: z.boolean().optional().describe('Перевести промпт на английский (по умолчанию авто при кириллице)'),
|
|
8
12
|
};
|
|
9
13
|
export async function generateVideoHandler(input, deps) {
|
|
14
|
+
const model = input.model ?? deps.config.videoModel;
|
|
15
|
+
const cost = estimateCost({ kind: 'video', model });
|
|
16
|
+
if (!input.confirm) {
|
|
17
|
+
return { content: [{ type: 'text', text: `Видео через ${model} стоит ${cost.text}. Это платно. Чтобы сгенерировать, вызови ещё раз с confirm: true.` }] };
|
|
18
|
+
}
|
|
10
19
|
try {
|
|
11
|
-
const
|
|
12
|
-
const media = await deps.client.generateVideo({ prompt:
|
|
20
|
+
const t = await maybeTranslate(input.prompt, deps, input.translate);
|
|
21
|
+
const media = await deps.client.generateVideo({ prompt: t.text, model });
|
|
13
22
|
const id = randomUUID().slice(0, 8);
|
|
14
23
|
const manifest = {
|
|
15
|
-
id, parentId: null, kind: 'video', prompt:
|
|
24
|
+
id, parentId: null, kind: 'video', prompt: t.text, model,
|
|
16
25
|
file: `${id}.${extFromMime(media.mimeType)}`, mimeType: media.mimeType,
|
|
17
26
|
createdAt: new Date().toISOString(),
|
|
18
27
|
};
|
|
19
28
|
await deps.store.save(manifest, media.data);
|
|
20
|
-
|
|
29
|
+
const note = t.translated ? ` Промпт переведён: "${t.text}".` : '';
|
|
30
|
+
return imageResult(media, `Видео готово. id=${id}, файл: ${manifest.file} (в ${deps.config.workingDir}). Стоимость: ${cost.text}.${note}`);
|
|
21
31
|
}
|
|
22
32
|
catch (err) {
|
|
23
33
|
return errorResult(err);
|
|
24
34
|
}
|
|
25
35
|
}
|
|
26
36
|
export function registerGenerateVideo(server, deps) {
|
|
27
|
-
server.registerTool('generate_video', { title: 'Generate video', description: 'Сгенерировать видео по тексту через Gemini (Veo).
|
|
28
|
-
// cast: handler returns our CallToolResult; SDK expects its own index-signature variant (runtime-compatible).
|
|
29
|
-
(input) => generateVideoHandler(input, deps));
|
|
37
|
+
server.registerTool('generate_video', { title: 'Generate video', description: 'Сгенерировать видео по тексту через Gemini (Veo). Платно: без confirm:true вернёт смету. Русский промпт переводится автоматически.', inputSchema: generateVideoInput }, (input) => generateVideoHandler(input, deps));
|
|
30
38
|
}
|
|
31
39
|
//# sourceMappingURL=generateVideo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateVideo.js","sourceRoot":"","sources":["../../src/tools/generateVideo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"generateVideo.js","sourceRoot":"","sources":["../../src/tools/generateVideo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { errorResult } from './result.js';
|
|
3
|
+
export const savePresetInput = {
|
|
4
|
+
name: z.string().describe('Имя пресета'),
|
|
5
|
+
style: z.string().describe('Описание стиля, которое подмешивается в промпт'),
|
|
6
|
+
};
|
|
7
|
+
export async function savePresetHandler(input, deps) {
|
|
8
|
+
try {
|
|
9
|
+
await deps.presets.save({ name: input.name, style: input.style });
|
|
10
|
+
return { content: [{ type: 'text', text: `Пресет "${input.name}" сохранён.` }] };
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
return errorResult(err);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export async function listPresetsHandler(_input, deps) {
|
|
17
|
+
const presets = await deps.presets.list();
|
|
18
|
+
if (presets.length === 0) {
|
|
19
|
+
return { content: [{ type: 'text', text: 'Пресетов пока нет. Создай через save_preset.' }] };
|
|
20
|
+
}
|
|
21
|
+
const lines = presets.map((p) => `• ${p.name}: ${p.style}`).join('\n');
|
|
22
|
+
return { content: [{ type: 'text', text: lines }] };
|
|
23
|
+
}
|
|
24
|
+
export function registerPresetTools(server, deps) {
|
|
25
|
+
server.registerTool('save_preset', { title: 'Save style preset', description: 'Сохранить именованный пресет стиля для повторного использования в генерации.', inputSchema: savePresetInput }, (input) => savePresetHandler(input, deps));
|
|
26
|
+
server.registerTool('list_presets', { title: 'List style presets', description: 'Показать сохранённые пресеты стиля.', inputSchema: {} }, () => listPresetsHandler({}, deps));
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/tools/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAE/D,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;CAC7E,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAsC,EACtC,IAAc;IAEd,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,CAAC,IAAI,aAAa,EAAE,CAAC,EAAE,CAAC;IACnF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAA6B,EAAE,IAAc;IACpF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8CAA8C,EAAE,CAAC,EAAE,CAAC;IAC/F,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,IAAc;IACnE,MAAM,CAAC,YAAY,CACjB,aAAa,EACb,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,8EAA8E,EAAE,WAAW,EAAE,eAAe,EAAE,EACzJ,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAQ,CACjD,CAAC;IACF,MAAM,CAAC,YAAY,CACjB,cAAc,EACd,EAAE,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,qCAAqC,EAAE,WAAW,EAAE,EAAE,EAAE,EACpG,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,EAAE,IAAI,CAAQ,CAC1C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { needsTranslation } from '../translate/detect.js';
|
|
2
|
+
export async function maybeTranslate(text, deps, override) {
|
|
3
|
+
const auto = deps.config.autoTranslate ?? true;
|
|
4
|
+
const should = override === true || (override !== false && auto && needsTranslation(text));
|
|
5
|
+
if (!should || !deps.client.translateToEnglish) {
|
|
6
|
+
return { text, translated: false };
|
|
7
|
+
}
|
|
8
|
+
const model = deps.config.translateModel ?? 'gemini-2.5-flash';
|
|
9
|
+
const translated = await deps.client.translateToEnglish(text, model);
|
|
10
|
+
return { text: translated, translated: translated !== text };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tools/translate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI1D,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,IAAc,EACd,QAAkB;IAElB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC;IAC/C,MAAM,MAAM,GAAG,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,IAAI,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,kBAAkB,CAAC;IAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACrE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,KAAK,IAAI,EAAE,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/translate/detect.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2DAA2D;AAC3D,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gemini-studio-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP server for iterative image & video generation via the Gemini API (Imagen 4, Gemini 3 Pro Image, Veo) — generate and refine in plain words, with lineage.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": { "gemini-studio-mcp": "dist/index.js" },
|