@0xmaxma/claude-gateway 2.0.11 → 2.0.13
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/build-provenance.json +4 -4
- package/dist/orchestration/bridge.d.ts +3 -0
- package/dist/orchestration/bridge.d.ts.map +1 -1
- package/dist/orchestration/bridge.js +22 -11
- package/dist/orchestration/bridge.js.map +1 -1
- package/dist/orchestration/config.d.ts +36 -0
- package/dist/orchestration/config.d.ts.map +1 -1
- package/dist/orchestration/config.js +14 -3
- package/dist/orchestration/config.js.map +1 -1
- package/dist/orchestration/delivery.d.ts +1 -0
- package/dist/orchestration/delivery.d.ts.map +1 -1
- package/dist/orchestration/delivery.js +1 -1
- package/dist/orchestration/delivery.js.map +1 -1
- package/dist/orchestration/file-delivery.d.ts.map +1 -1
- package/dist/orchestration/file-delivery.js +47 -3
- package/dist/orchestration/file-delivery.js.map +1 -1
- package/dist/orchestration/narrate.d.ts +42 -0
- package/dist/orchestration/narrate.d.ts.map +1 -0
- package/dist/orchestration/narrate.js +197 -0
- package/dist/orchestration/narrate.js.map +1 -0
- package/dist/orchestration/process-turn.js +1 -1
- package/dist/orchestration/process-turn.js.map +1 -1
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +5 -0
- package/dist/orchestration/runtime.js.map +1 -1
- package/dist/orchestration/task-files.d.ts +10 -1
- package/dist/orchestration/task-files.d.ts.map +1 -1
- package/dist/orchestration/task-files.js +46 -8
- package/dist/orchestration/task-files.js.map +1 -1
- package/dist/safemode/context.d.ts.map +1 -1
- package/dist/safemode/context.js +169 -72
- package/dist/safemode/context.js.map +1 -1
- package/dist/safemode/external-owners.d.ts +4 -1
- package/dist/safemode/external-owners.d.ts.map +1 -1
- package/dist/safemode/external-owners.js +36 -9
- package/dist/safemode/external-owners.js.map +1 -1
- package/dist/safemode/native.d.ts.map +1 -1
- package/dist/safemode/native.js +16 -10
- package/dist/safemode/native.js.map +1 -1
- package/dist/session/runtime-profile.d.ts.map +1 -1
- package/dist/session/runtime-profile.js +2 -1
- package/dist/session/runtime-profile.js.map +1 -1
- package/dist/voice/line-audio.d.ts +10 -1
- package/dist/voice/line-audio.d.ts.map +1 -1
- package/dist/voice/line-audio.js +19 -6
- package/dist/voice/line-audio.js.map +1 -1
- package/dist/voice/narrate-split.d.ts +17 -0
- package/dist/voice/narrate-split.d.ts.map +1 -0
- package/dist/voice/narrate-split.js +77 -0
- package/dist/voice/narrate-split.js.map +1 -0
- package/mcp/lazy-tools.test.ts +2 -1
- package/mcp/modules.ts +2 -0
- package/mcp/server.ts +2 -1
- package/mcp/tools/narrate/module.ts +42 -0
- package/mcp/tools/tasks/module.ts +7 -2
- package/package.json +1 -1
- package/scripts/orchestration/smoke-safemode-codex.cjs +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ToolModule, McpToolDefinition, McpToolResult, ToolVisibility } from '../../types';
|
|
2
|
+
import { callTaskBridge } from '../tasks/module';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Long-form narration (worker only). TTS credentials live in the gateway, so this
|
|
6
|
+
* module just forwards to the task bridge; the gateway splits the text, synthesizes
|
|
7
|
+
* it piece by piece and stages the resulting audio files for the agent's reply.
|
|
8
|
+
*/
|
|
9
|
+
export const NARRATE_TOOL: McpToolDefinition = {
|
|
10
|
+
name: 'narrate',
|
|
11
|
+
description:
|
|
12
|
+
'Narrate text to speech: read text aloud to the user as a sequence of voice/audio messages (TTS). Use this when the user asks to HEAR a page, post, document or file — ' +
|
|
13
|
+
'pass the full text (or a file path inside this task) and every character is spoken, in order. ' +
|
|
14
|
+
'Pass exactly one of `text` or `path`. Do NOT summarize or shorten the text you pass unless the user asked for a summary; ' +
|
|
15
|
+
'the tool never rewrites it. This tool cannot fetch URLs: fetch the page yourself and pass its text. ' +
|
|
16
|
+
'The audio files are staged automatically (do not call task_stage_file for them). ' +
|
|
17
|
+
'Afterwards finish the task with ONE short sentence saying how many parts were prepared (your final reply must be non-empty so the audio attaches); ' +
|
|
18
|
+
'do not repeat the content. If the result has `ok:false`, report `stopped_reason` and how many parts were staged. ' +
|
|
19
|
+
'Host workers only: container workers cannot use media tools.',
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
text: { type: 'string', description: 'The exact text to read aloud.' },
|
|
24
|
+
path: { type: 'string', description: 'Absolute path of a UTF-8 text file inside this task scope or an attachment.' },
|
|
25
|
+
},
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export class NarrateModule implements ToolModule {
|
|
31
|
+
id = 'narrate';
|
|
32
|
+
toolVisibility: ToolVisibility = 'all-configured';
|
|
33
|
+
|
|
34
|
+
isEnabled(): boolean {
|
|
35
|
+
return process.env.GATEWAY_ORCHESTRATION_ROLE === 'worker' && process.env.GATEWAY_ORCHESTRATION_MEDIA === 'true' && Boolean(process.env.GATEWAY_ORCHESTRATION_TICKET_FILE);
|
|
36
|
+
}
|
|
37
|
+
getTools(): McpToolDefinition[] { return [NARRATE_TOOL]; }
|
|
38
|
+
handleTool(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<McpToolResult> {
|
|
39
|
+
if (name !== 'narrate') return Promise.resolve({ content: [{ type: 'text', text: `unknown tool: ${name}` }], isError: true });
|
|
40
|
+
return callTaskBridge(name, args, crypto.randomUUID(), signal ?? new AbortController().signal);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -15,13 +15,18 @@ export const WORKER_REPORT_TOOLS: McpToolDefinition[] = [
|
|
|
15
15
|
{ name: 'task_request_input', description: 'Ask the user for information required by your task, then end this turn immediately.', inputSchema: schema({ question: text }, ['question']) },
|
|
16
16
|
];
|
|
17
17
|
|
|
18
|
+
const LONG_RUNNING_TOOLS = new Set(['narrate']);
|
|
19
|
+
export const LONG_RUNNING_MAX_MS = 2 * 60 * 60 * 1000;
|
|
18
20
|
export async function callTaskBridge(tool: string, args: Record<string, unknown>, requestId: string, signal: AbortSignal): Promise<McpToolResult> {
|
|
19
21
|
// Rotated by the gateway at each decision/attempt boundary. A loaded token is
|
|
20
22
|
// immutable for this request; late requests cannot borrow the next decision.
|
|
21
23
|
const { readFile } = await import('node:fs/promises');
|
|
22
24
|
const scope = JSON.parse(await readFile(process.env.GATEWAY_ORCHESTRATION_TICKET_FILE!, 'utf8')) as { url: string; token: string };
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
// Bun's fetch gives up after 300s without a response. Narration answers only when every part is spoken
|
|
26
|
+
// (up to maxParts x partTimeoutMs), so that call alone has no idle timeout, bounded by an overall maximum.
|
|
27
|
+
const long = LONG_RUNNING_TOOLS.has(tool);
|
|
28
|
+
const response = await fetch(scope.url, { method: 'POST', signal: long ? AbortSignal.any([signal, AbortSignal.timeout(LONG_RUNNING_MAX_MS)]) : signal, ...(long ? { timeout: false } : {}), headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${scope.token}` },
|
|
29
|
+
body: JSON.stringify({ tool, args, action_id: requestId }) } as RequestInit);
|
|
25
30
|
const body = await response.text();
|
|
26
31
|
if(response.ok && tool==='task_status') {
|
|
27
32
|
const value=JSON.parse(body),image=value.screenshot;
|
package/package.json
CHANGED
|
@@ -53,7 +53,7 @@ const { buildNativeInvocation } = require('../../dist/safemode/native');
|
|
|
53
53
|
const id = events.find(event => event.type === 'thread.started')?.thread_id;
|
|
54
54
|
assert(id); if (nativeSessionId) assert.equal(id, nativeSessionId);
|
|
55
55
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
56
|
-
assert.equal(fs.existsSync(marker), false, 'notify executed outside the
|
|
56
|
+
assert.equal(fs.existsSync(marker), false, 'notify executed outside the investigation workspace');
|
|
57
57
|
return id;
|
|
58
58
|
}
|
|
59
59
|
await run(await run());
|