@0xmaxma/claude-gateway 1.8.4 → 1.8.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/README.md +11 -2
- package/config.template.json +5 -3
- package/dist/agent/model-catalog.d.ts.map +1 -1
- package/dist/agent/model-catalog.js +5 -13
- package/dist/agent/model-catalog.js.map +1 -1
- package/dist/agent/runner.d.ts +1 -1
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +22 -3
- package/dist/agent/runner.js.map +1 -1
- package/dist/api/apps-router.d.ts.map +1 -1
- package/dist/api/apps-router.js +31 -9
- package/dist/api/apps-router.js.map +1 -1
- package/dist/api/gateway-router.js +1 -1
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/packages.d.ts.map +1 -1
- package/dist/api/packages.js +17 -1
- package/dist/api/packages.js.map +1 -1
- package/dist/api/share-router.d.ts +8 -0
- package/dist/api/share-router.d.ts.map +1 -1
- package/dist/api/share-router.js +100 -10
- package/dist/api/share-router.js.map +1 -1
- package/dist/apps/agent-manager.d.ts +35 -2
- package/dist/apps/agent-manager.d.ts.map +1 -1
- package/dist/apps/agent-manager.js +131 -15
- package/dist/apps/agent-manager.js.map +1 -1
- package/dist/apps/installer.d.ts +49 -1
- package/dist/apps/installer.d.ts.map +1 -1
- package/dist/apps/installer.js +74 -17
- package/dist/apps/installer.js.map +1 -1
- package/dist/cli/args.d.ts +6 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/logs.d.ts.map +1 -1
- package/dist/cli/commands/logs.js +91 -18
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/service.d.ts.map +1 -1
- package/dist/cli/commands/service.js +61 -7
- package/dist/cli/commands/service.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +12 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +34 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +56 -10
- package/dist/cli/output.js.map +1 -1
- package/dist/config/claude-settings.d.ts +41 -0
- package/dist/config/claude-settings.d.ts.map +1 -0
- package/dist/config/claude-settings.js +102 -0
- package/dist/config/claude-settings.js.map +1 -0
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/session/process.d.ts +43 -1
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +154 -9
- package/dist/session/process.js.map +1 -1
- package/dist/share/share-store.d.ts +45 -4
- package/dist/share/share-store.d.ts.map +1 -1
- package/dist/share/share-store.js +127 -23
- package/dist/share/share-store.js.map +1 -1
- package/dist/shutdown-signals.d.ts +18 -0
- package/dist/shutdown-signals.d.ts.map +1 -1
- package/dist/shutdown-signals.js +33 -2
- package/dist/shutdown-signals.js.map +1 -1
- package/mcp/server.ts +2 -2
- package/mcp/tools/image/module.ts +10 -3
- package/mcp/tools/share-file/module.ts +169 -0
- package/mcp/tools/shared/share-client.ts +8 -4
- package/mcp/tools/telegram/receiver-server.ts +12 -2
- package/package.json +1 -1
- package/mcp/tools/share-image/module.ts +0 -120
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { ToolModule, McpToolDefinition, McpToolResult, ToolVisibility } from '../../types';
|
|
2
|
+
import {
|
|
3
|
+
ShareClientError,
|
|
4
|
+
createShares,
|
|
5
|
+
revokeShare,
|
|
6
|
+
shareBridgeEnabled,
|
|
7
|
+
type ShareRef,
|
|
8
|
+
} from '../shared/share-client';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Standalone share_file MCP tool (#70, plan §15) — explicit create/revoke of
|
|
12
|
+
* short-lived public URLs for a file in the agent's media directory. There is
|
|
13
|
+
* deliberately NO list action (shares are unenumerable, §10). generate_image
|
|
14
|
+
* auto-normalizes refs through the same gateway API, so normal image editing
|
|
15
|
+
* never needs this tool; it exists for explicit workflows (e.g. handing a
|
|
16
|
+
* temporary URL to an external service).
|
|
17
|
+
*
|
|
18
|
+
* #444: was `share_image` back when the bridge could only carry images. The
|
|
19
|
+
* old name stays registered as a thin alias — it is baked into agent
|
|
20
|
+
* workspaces (AGENTS.md, skills, memories) that we do not get to rewrite.
|
|
21
|
+
*/
|
|
22
|
+
export class ShareFileModule implements ToolModule {
|
|
23
|
+
id = 'share-file';
|
|
24
|
+
toolVisibility: ToolVisibility = 'all-configured';
|
|
25
|
+
|
|
26
|
+
isEnabled(): boolean {
|
|
27
|
+
return shareBridgeEnabled();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getTools(): McpToolDefinition[] {
|
|
31
|
+
return shareFileToolDefs;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async handleTool(name: string, args: Record<string, unknown>): Promise<McpToolResult> {
|
|
35
|
+
if (name !== 'share_file' && name !== LEGACY_TOOL_NAME) {
|
|
36
|
+
return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };
|
|
37
|
+
}
|
|
38
|
+
const legacy = name === LEGACY_TOOL_NAME;
|
|
39
|
+
const action = typeof args.action === 'string' ? args.action : 'create';
|
|
40
|
+
switch (action) {
|
|
41
|
+
case 'create':
|
|
42
|
+
return this.handleCreate(args, legacy);
|
|
43
|
+
case 'revoke':
|
|
44
|
+
return this.handleRevoke(args);
|
|
45
|
+
default:
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: 'text', text: `share_file: unknown action "${action}" (expected create | revoke)` }],
|
|
48
|
+
isError: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private async handleCreate(args: Record<string, unknown>, legacy: boolean): Promise<McpToolResult> {
|
|
54
|
+
const single = typeof args.path === 'string' && args.path.trim() ? [args.path.trim()] : [];
|
|
55
|
+
const many = Array.isArray(args.paths)
|
|
56
|
+
? (args.paths.filter((p) => typeof p === 'string' && p.trim()) as string[])
|
|
57
|
+
: [];
|
|
58
|
+
if (single.length && many.length) {
|
|
59
|
+
return { content: [{ type: 'text', text: 'share_file: pass either "path" or "paths", not both.' }], isError: true };
|
|
60
|
+
}
|
|
61
|
+
const paths = single.length ? single : many;
|
|
62
|
+
if (!paths.length) {
|
|
63
|
+
return { content: [{ type: 'text', text: 'share_file: action="create" requires "path" or "paths".' }], isError: true };
|
|
64
|
+
}
|
|
65
|
+
const refs: ShareRef[] = paths.map((p) =>
|
|
66
|
+
p.startsWith('artifact:') ? { artifact_id: p.slice('artifact:'.length) } : { path: p },
|
|
67
|
+
);
|
|
68
|
+
const opts: { purpose?: string; ttlSeconds?: number; allowDocuments: boolean } = {
|
|
69
|
+
// share_file is the agent's explicit "publish this file" verb, so it opts
|
|
70
|
+
// into the full share allowlist (images + PDF). The legacy share_image
|
|
71
|
+
// name does NOT: an instruction written against it meant "share an
|
|
72
|
+
// image", and widening it would retroactively change what an existing
|
|
73
|
+
// call site's live token can serve — a share minted on chart.png would
|
|
74
|
+
// start serving a PDF if the file were later overwritten, where before it
|
|
75
|
+
// failed closed with a 404. The narrow image consumers (line_image,
|
|
76
|
+
// generate_image ref normalization) stay strict for the same reason.
|
|
77
|
+
allowDocuments: !legacy,
|
|
78
|
+
};
|
|
79
|
+
if (typeof args.purpose === 'string' && args.purpose.trim()) opts.purpose = args.purpose.trim();
|
|
80
|
+
if (typeof args.ttl_seconds === 'number' && args.ttl_seconds > 0) opts.ttlSeconds = args.ttl_seconds;
|
|
81
|
+
try {
|
|
82
|
+
const items = await createShares(refs, opts);
|
|
83
|
+
return { content: [{ type: 'text', text: JSON.stringify({ items }, null, 2) }] };
|
|
84
|
+
} catch (err) {
|
|
85
|
+
return this.mapError(err, legacy);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private async handleRevoke(args: Record<string, unknown>): Promise<McpToolResult> {
|
|
90
|
+
const shareId = typeof args.share_id === 'string' ? args.share_id.trim() : '';
|
|
91
|
+
if (!shareId) {
|
|
92
|
+
return { content: [{ type: 'text', text: 'share_file: action="revoke" requires "share_id".' }], isError: true };
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
await revokeShare(shareId);
|
|
96
|
+
return { content: [{ type: 'text', text: JSON.stringify({ revoked: true, share_id: shareId }) }] };
|
|
97
|
+
} catch (err) {
|
|
98
|
+
return this.mapError(err);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private mapError(err: unknown, legacy = false): McpToolResult {
|
|
103
|
+
if (err instanceof ShareClientError) {
|
|
104
|
+
// Without this the agent hits a dead end: it asked the image-only name to
|
|
105
|
+
// share a PDF and gets a bare 415 with no hint that a wider tool exists.
|
|
106
|
+
const hint =
|
|
107
|
+
legacy && err.code === 'unsupported_file_type'
|
|
108
|
+
? ' — share_image is image-only; call share_file for documents.'
|
|
109
|
+
: '';
|
|
110
|
+
return { content: [{ type: 'text', text: `share_file: ${err.code}: ${err.message}${hint}` }], isError: true };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
content: [{ type: 'text', text: `share_file: gateway unavailable: ${(err as Error).message}` }],
|
|
114
|
+
isError: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const LEGACY_TOOL_NAME = 'share_image';
|
|
120
|
+
|
|
121
|
+
const shareFileInputSchema = {
|
|
122
|
+
type: 'object',
|
|
123
|
+
properties: {
|
|
124
|
+
action: { type: 'string', enum: ['create', 'revoke'], description: 'create (default) | revoke' },
|
|
125
|
+
path: { type: 'string', description: 'One media path (e.g. "media/session-1/report.pdf") or "artifact:<id>" to share.' },
|
|
126
|
+
paths: { type: 'array', items: { type: 'string' }, description: 'Multiple media paths / artifact refs (max 5).' },
|
|
127
|
+
ttl_seconds: { type: 'number', description: 'Optional lifetime in seconds (default 1800).' },
|
|
128
|
+
purpose: { type: 'string', description: 'Optional purpose tag (default "codex_ref").' },
|
|
129
|
+
share_id: { type: 'string', description: 'Share id to revoke (required for action="revoke").' },
|
|
130
|
+
},
|
|
131
|
+
required: [],
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// The alias is image-only, so it must not advertise the PDF example: an agent
|
|
135
|
+
// reading its schema would be told a document is acceptable and get a 415.
|
|
136
|
+
// Same shape, image wording — a separate object costs nothing, since both defs
|
|
137
|
+
// are serialized in full either way.
|
|
138
|
+
const shareImageInputSchema = {
|
|
139
|
+
...shareFileInputSchema,
|
|
140
|
+
properties: {
|
|
141
|
+
...shareFileInputSchema.properties,
|
|
142
|
+
path: { type: 'string', description: 'One media path (e.g. "media/session-1/chart.png") or "artifact:<id>" to share.' },
|
|
143
|
+
paths: { type: 'array', items: { type: 'string' }, description: 'Multiple media image paths / artifact refs (max 5).' },
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const shareFileToolDefs: McpToolDefinition[] = [
|
|
148
|
+
{
|
|
149
|
+
name: 'share_file',
|
|
150
|
+
description:
|
|
151
|
+
'Create or revoke a SHORT-LIVED public URL for a file in this agent\'s media directory (PNG, JPEG, WebP or PDF). ' +
|
|
152
|
+
'action="create" takes "path" (one media path or artifact:<id>) or "paths" (up to 5) and returns ' +
|
|
153
|
+
'{ share_id, url, expires_at } per file — the URL needs no auth and expires automatically (default 30 min). ' +
|
|
154
|
+
'action="revoke" takes "share_id" and invalidates the URL immediately. ' +
|
|
155
|
+
'You normally do NOT need this for image editing: generate_image converts local/artifact references ' +
|
|
156
|
+
'to share URLs automatically. There is no list action.',
|
|
157
|
+
inputSchema: shareFileInputSchema,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
// Deprecated #444 alias, kept so agent instructions written against the old
|
|
161
|
+
// name keep working — and kept IMAGE-ONLY, which is what those instructions
|
|
162
|
+
// meant and what the name still promises. Description is deliberately one
|
|
163
|
+
// line: it must not cost a second copy of the real tool's context budget.
|
|
164
|
+
name: LEGACY_TOOL_NAME,
|
|
165
|
+
description:
|
|
166
|
+
'Deprecated image-only alias for share_file — use share_file instead, which also shares PDFs.',
|
|
167
|
+
inputSchema: shareImageInputSchema,
|
|
168
|
+
},
|
|
169
|
+
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* share/artifact store. They call the authenticated
|
|
2
|
+
* File share bridge client (#70, widened past images in #444) — the ONLY way
|
|
3
|
+
* MCP subprocesses touch the share/artifact store. They call the authenticated
|
|
4
|
+
* local Gateway HTTP API
|
|
4
5
|
* (GATEWAY_API_URL + GATEWAY_API_KEY, both already injected into the session
|
|
5
6
|
* subprocess env) and NEVER open the SQLite DB themselves (plan §9/§10).
|
|
6
7
|
*
|
|
@@ -53,7 +54,7 @@ export type CatalogItem = {
|
|
|
53
54
|
desc?: string;
|
|
54
55
|
};
|
|
55
56
|
|
|
56
|
-
/** Error carrying the gateway's stable machine-readable code (e.g.
|
|
57
|
+
/** Error carrying the gateway's stable machine-readable code (e.g. share_ref_not_found). */
|
|
57
58
|
export class ShareClientError extends Error {
|
|
58
59
|
readonly code: string;
|
|
59
60
|
readonly status: number;
|
|
@@ -109,7 +110,7 @@ async function callGateway(
|
|
|
109
110
|
/** Mint short-lived share URLs for local/artifact refs — order preserved. */
|
|
110
111
|
export async function createShares(
|
|
111
112
|
refs: ShareRef[],
|
|
112
|
-
opts: { purpose?: string; ttlSeconds?: number } = {},
|
|
113
|
+
opts: { purpose?: string; ttlSeconds?: number; allowDocuments?: boolean } = {},
|
|
113
114
|
): Promise<ShareItem[]> {
|
|
114
115
|
const body: Record<string, unknown> = {
|
|
115
116
|
agent_id: process.env.GATEWAY_AGENT_ID,
|
|
@@ -118,6 +119,9 @@ export async function createShares(
|
|
|
118
119
|
refs,
|
|
119
120
|
};
|
|
120
121
|
if (opts.ttlSeconds !== undefined) body.ttl_seconds = opts.ttlSeconds;
|
|
122
|
+
// Opt-in only: image callers (line_image, generate_image refs) must keep
|
|
123
|
+
// getting a hard rejection for a non-image ref.
|
|
124
|
+
if (opts.allowDocuments) body.allow_documents = true;
|
|
121
125
|
const { status, json } = await callGateway('POST', '/api/v1/shares', body);
|
|
122
126
|
if (status !== 201) {
|
|
123
127
|
const code = typeof json.code === 'string' ? json.code : 'share_failed';
|
|
@@ -884,12 +884,22 @@ const BOT_COMMANDS = [
|
|
|
884
884
|
// reached only when the gateway call itself fails, so it is two fallbacks deep
|
|
885
885
|
// and will drift — keep it roughly in step with DEFAULT_MODELS
|
|
886
886
|
// (src/agent/runner.ts) and config.template.json gateway.models.
|
|
887
|
+
//
|
|
888
|
+
// `alias` is never read in this process: validModelRows() keeps only id and
|
|
889
|
+
// label, and the picker's callback data is `model:<id>`. It is carried anyway
|
|
890
|
+
// so this list stays diffable against the two registries it mirrors, and so
|
|
891
|
+
// the cross-registry sync test can compare alias mappings — that test is the
|
|
892
|
+
// only thing standing between this copy and the silent drift that already lost
|
|
893
|
+
// it Opus 5 once. Do not drop the column to "clean up"; it would blind the
|
|
894
|
+
// guard, not simplify it.
|
|
887
895
|
const AVAILABLE_MODELS = [
|
|
888
|
-
{ id: 'claude-fable-5[1m]',
|
|
896
|
+
{ id: 'claude-fable-5-1[1m]', label: 'Fable 5.1 (1M)', alias: 'fable[1m]' },
|
|
897
|
+
{ id: 'claude-fable-5[1m]', label: 'Fable 5 (1M)', alias: 'fable5[1m]' },
|
|
889
898
|
{ id: 'claude-opus-5[1m]', label: 'Opus 5 (1M)', alias: 'opus[1m]' },
|
|
890
899
|
{ id: 'claude-opus-4-8[1m]', label: 'Opus 4.8 (1M)', alias: 'opus48[1m]' },
|
|
891
900
|
{ id: 'claude-sonnet-5[1m]', label: 'Sonnet 5 (1M)', alias: 'sonnet[1m]' },
|
|
892
|
-
{ id: 'claude-fable-5',
|
|
901
|
+
{ id: 'claude-fable-5-1', label: 'Fable 5.1', alias: 'fable' },
|
|
902
|
+
{ id: 'claude-fable-5', label: 'Fable 5', alias: 'fable5' },
|
|
893
903
|
{ id: 'claude-opus-5', label: 'Opus 5', alias: 'opus' },
|
|
894
904
|
{ id: 'claude-opus-4-8', label: 'Opus 4.8', alias: 'opus48' },
|
|
895
905
|
{ id: 'claude-opus-4-6', label: 'Opus 4.6', alias: 'opus46' },
|
package/package.json
CHANGED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import type { ToolModule, McpToolDefinition, McpToolResult, ToolVisibility } from '../../types';
|
|
2
|
-
import {
|
|
3
|
-
ShareClientError,
|
|
4
|
-
createShares,
|
|
5
|
-
revokeShare,
|
|
6
|
-
shareBridgeEnabled,
|
|
7
|
-
type ShareRef,
|
|
8
|
-
} from '../shared/share-client';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Standalone share_image MCP tool (#70, plan §15) — explicit create/revoke of
|
|
12
|
-
* short-lived public image URLs. There is deliberately NO list action (shares
|
|
13
|
-
* are unenumerable, §10). generate_image auto-normalizes refs through the same
|
|
14
|
-
* gateway API, so normal image editing never needs this tool; it exists for
|
|
15
|
-
* explicit workflows (e.g. handing a temporary URL to an external service).
|
|
16
|
-
*/
|
|
17
|
-
export class ShareImageModule implements ToolModule {
|
|
18
|
-
id = 'share-image';
|
|
19
|
-
toolVisibility: ToolVisibility = 'all-configured';
|
|
20
|
-
|
|
21
|
-
isEnabled(): boolean {
|
|
22
|
-
return shareBridgeEnabled();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getTools(): McpToolDefinition[] {
|
|
26
|
-
return shareImageToolDefs;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async handleTool(name: string, args: Record<string, unknown>): Promise<McpToolResult> {
|
|
30
|
-
if (name !== 'share_image') {
|
|
31
|
-
return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };
|
|
32
|
-
}
|
|
33
|
-
const action = typeof args.action === 'string' ? args.action : 'create';
|
|
34
|
-
switch (action) {
|
|
35
|
-
case 'create':
|
|
36
|
-
return this.handleCreate(args);
|
|
37
|
-
case 'revoke':
|
|
38
|
-
return this.handleRevoke(args);
|
|
39
|
-
default:
|
|
40
|
-
return {
|
|
41
|
-
content: [{ type: 'text', text: `share_image: unknown action "${action}" (expected create | revoke)` }],
|
|
42
|
-
isError: true,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private async handleCreate(args: Record<string, unknown>): Promise<McpToolResult> {
|
|
48
|
-
const single = typeof args.path === 'string' && args.path.trim() ? [args.path.trim()] : [];
|
|
49
|
-
const many = Array.isArray(args.paths)
|
|
50
|
-
? (args.paths.filter((p) => typeof p === 'string' && p.trim()) as string[])
|
|
51
|
-
: [];
|
|
52
|
-
if (single.length && many.length) {
|
|
53
|
-
return { content: [{ type: 'text', text: 'share_image: pass either "path" or "paths", not both.' }], isError: true };
|
|
54
|
-
}
|
|
55
|
-
const paths = single.length ? single : many;
|
|
56
|
-
if (!paths.length) {
|
|
57
|
-
return { content: [{ type: 'text', text: 'share_image: action="create" requires "path" or "paths".' }], isError: true };
|
|
58
|
-
}
|
|
59
|
-
const refs: ShareRef[] = paths.map((p) =>
|
|
60
|
-
p.startsWith('artifact:') ? { artifact_id: p.slice('artifact:'.length) } : { path: p },
|
|
61
|
-
);
|
|
62
|
-
const opts: { purpose?: string; ttlSeconds?: number } = {};
|
|
63
|
-
if (typeof args.purpose === 'string' && args.purpose.trim()) opts.purpose = args.purpose.trim();
|
|
64
|
-
if (typeof args.ttl_seconds === 'number' && args.ttl_seconds > 0) opts.ttlSeconds = args.ttl_seconds;
|
|
65
|
-
try {
|
|
66
|
-
const items = await createShares(refs, opts);
|
|
67
|
-
return { content: [{ type: 'text', text: JSON.stringify({ items }, null, 2) }] };
|
|
68
|
-
} catch (err) {
|
|
69
|
-
return this.mapError(err);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private async handleRevoke(args: Record<string, unknown>): Promise<McpToolResult> {
|
|
74
|
-
const shareId = typeof args.share_id === 'string' ? args.share_id.trim() : '';
|
|
75
|
-
if (!shareId) {
|
|
76
|
-
return { content: [{ type: 'text', text: 'share_image: action="revoke" requires "share_id".' }], isError: true };
|
|
77
|
-
}
|
|
78
|
-
try {
|
|
79
|
-
await revokeShare(shareId);
|
|
80
|
-
return { content: [{ type: 'text', text: JSON.stringify({ revoked: true, share_id: shareId }) }] };
|
|
81
|
-
} catch (err) {
|
|
82
|
-
return this.mapError(err);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
private mapError(err: unknown): McpToolResult {
|
|
87
|
-
if (err instanceof ShareClientError) {
|
|
88
|
-
return { content: [{ type: 'text', text: `share_image: ${err.code}: ${err.message}` }], isError: true };
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
content: [{ type: 'text', text: `share_image: gateway unavailable: ${(err as Error).message}` }],
|
|
92
|
-
isError: true,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const shareImageToolDefs: McpToolDefinition[] = [
|
|
98
|
-
{
|
|
99
|
-
name: 'share_image',
|
|
100
|
-
description:
|
|
101
|
-
'Create or revoke a SHORT-LIVED public URL for an image in this agent\'s media directory. ' +
|
|
102
|
-
'action="create" takes "path" (one media path or artifact:<id>) or "paths" (up to 5) and returns ' +
|
|
103
|
-
'{ share_id, url, expires_at } per image — the URL needs no auth and expires automatically (default 30 min). ' +
|
|
104
|
-
'action="revoke" takes "share_id" and invalidates the URL immediately. ' +
|
|
105
|
-
'You normally do NOT need this for image editing: generate_image converts local/artifact references ' +
|
|
106
|
-
'to share URLs automatically. There is no list action.',
|
|
107
|
-
inputSchema: {
|
|
108
|
-
type: 'object',
|
|
109
|
-
properties: {
|
|
110
|
-
action: { type: 'string', enum: ['create', 'revoke'], description: 'create (default) | revoke' },
|
|
111
|
-
path: { type: 'string', description: 'One media path (e.g. "media/session-1/image.png") or "artifact:<id>" to share.' },
|
|
112
|
-
paths: { type: 'array', items: { type: 'string' }, description: 'Multiple media paths / artifact refs (max 5).' },
|
|
113
|
-
ttl_seconds: { type: 'number', description: 'Optional lifetime in seconds (default 1800).' },
|
|
114
|
-
purpose: { type: 'string', description: 'Optional purpose tag (default "codex_ref").' },
|
|
115
|
-
share_id: { type: 'string', description: 'Share id to revoke (required for action="revoke").' },
|
|
116
|
-
},
|
|
117
|
-
required: [],
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
];
|