mcacp 0.1.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/LICENSE +190 -0
- package/README.md +195 -0
- package/dist/acp/agent-requests.d.ts +19 -0
- package/dist/acp/agent-requests.js +166 -0
- package/dist/acp/agent-requests.js.map +1 -0
- package/dist/acp/lifecycle.d.ts +50 -0
- package/dist/acp/lifecycle.js +127 -0
- package/dist/acp/lifecycle.js.map +1 -0
- package/dist/acp/status.d.ts +31 -0
- package/dist/acp/status.js +72 -0
- package/dist/acp/status.js.map +1 -0
- package/dist/acp/transport.d.ts +34 -0
- package/dist/acp/transport.js +175 -0
- package/dist/acp/transport.js.map +1 -0
- package/dist/config/index.d.ts +27 -0
- package/dist/config/index.js +162 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions/index.d.ts +16 -0
- package/dist/permissions/index.js +70 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/registry/index.d.ts +52 -0
- package/dist/registry/index.js +240 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +271 -0
- package/dist/server/index.js.map +1 -0
- package/dist/sessions/index.d.ts +91 -0
- package/dist/sessions/index.js +151 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/prompt.d.ts +78 -0
- package/dist/sessions/prompt.js +361 -0
- package/dist/sessions/prompt.js.map +1 -0
- package/dist/types/acp.d.ts +343 -0
- package/dist/types/acp.js +17 -0
- package/dist/types/acp.js.map +1 -0
- package/dist/types/config.d.ts +135 -0
- package/dist/types/config.js +43 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/tools.d.ts +619 -0
- package/dist/types/tools.js +441 -0
- package/dist/types/tools.js.map +1 -0
- package/docs/configuration.md +164 -0
- package/package.json +58 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { resolve, dirname } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { loadConfig, discoverEditorAgents } from '../config/index.js';
|
|
8
|
+
import { RegistryManager } from '../registry/index.js';
|
|
9
|
+
import { LifecycleManager } from '../acp/lifecycle.js';
|
|
10
|
+
import { SessionManager } from '../sessions/index.js';
|
|
11
|
+
import { PromptHandler } from '../sessions/prompt.js';
|
|
12
|
+
import { PermissionEngine } from '../permissions/index.js';
|
|
13
|
+
import { AgentRequestHandler } from '../acp/agent-requests.js';
|
|
14
|
+
export async function createServer(configPath) {
|
|
15
|
+
const config = loadConfig(configPath);
|
|
16
|
+
const registry = new RegistryManager(config);
|
|
17
|
+
const lifecycle = new LifecycleManager(config, registry.getInstalled());
|
|
18
|
+
const sessions = new SessionManager(config, lifecycle);
|
|
19
|
+
const permissions = new PermissionEngine();
|
|
20
|
+
const promptHandler = new PromptHandler(lifecycle, sessions, permissions, config);
|
|
21
|
+
const agentRequests = new AgentRequestHandler();
|
|
22
|
+
const server = new McpServer({ name: 'mcacp', version: '0.1.0' });
|
|
23
|
+
permissions.setElicitationSender(async (message, schema) => {
|
|
24
|
+
const result = await server.server.elicitInput({
|
|
25
|
+
message,
|
|
26
|
+
requestedSchema: schema,
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
action: result.action,
|
|
30
|
+
content: result.content,
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
// ---- Registry tools ----
|
|
34
|
+
server.tool('list_installed_agents', 'List all locally installed ACP agents with their id, name, version, and description.', {}, async () => ({
|
|
35
|
+
content: [{ type: 'text', text: JSON.stringify(registry.listInstalled(), null, 2) }],
|
|
36
|
+
}));
|
|
37
|
+
server.tool('registry_search', 'Search configured ACP agent registries for available agents.', {
|
|
38
|
+
query: z.string().optional().describe('Search string to match against name, description, authors'),
|
|
39
|
+
showIncompatible: z.boolean().default(false).describe('Include platform-incompatible agents'),
|
|
40
|
+
}, async ({ query, showIncompatible }) => ({
|
|
41
|
+
content: [{ type: 'text', text: JSON.stringify(await registry.search(query, showIncompatible), null, 2) }],
|
|
42
|
+
}));
|
|
43
|
+
server.tool('agent_install', 'Install an ACP agent from the registry.', {
|
|
44
|
+
agentId: z.string().describe('Registry ID of the agent'),
|
|
45
|
+
version: z.string().optional().describe('Specific version (default: latest)'),
|
|
46
|
+
}, async ({ agentId, version }) => {
|
|
47
|
+
const installed = await registry.install(agentId, version);
|
|
48
|
+
lifecycle.updateInstalledAgents(registry.getInstalled());
|
|
49
|
+
return { content: [{ type: 'text', text: JSON.stringify(installed, null, 2) }] };
|
|
50
|
+
});
|
|
51
|
+
server.tool('agent_uninstall', 'Remove a locally installed ACP agent.', { agentId: z.string().describe('ID of the agent to uninstall') }, async ({ agentId }) => {
|
|
52
|
+
registry.uninstall(agentId);
|
|
53
|
+
lifecycle.updateInstalledAgents(registry.getInstalled());
|
|
54
|
+
return { content: [{ type: 'text', text: `Uninstalled ${agentId}` }] };
|
|
55
|
+
});
|
|
56
|
+
server.tool('agent_check_upgrades', 'Check all installed agents for available version upgrades.', {}, async () => ({
|
|
57
|
+
content: [{ type: 'text', text: JSON.stringify(await registry.checkUpgrades(), null, 2) }],
|
|
58
|
+
}));
|
|
59
|
+
server.tool('discover_agents', 'Scan editor configs (Zed settings.json, JetBrains acp.json) for ACP agents. Returns agents with command/args/env and source. To import, add them to agent_servers in your mcacp.json and call reload_config.', {}, async () => ({
|
|
60
|
+
content: [{ type: 'text', text: JSON.stringify(discoverEditorAgents(), null, 2) }],
|
|
61
|
+
}));
|
|
62
|
+
server.tool('reload_config', 'Reload configuration from disk. Use after editing mcacp.json to pick up new agent_servers entries or changed settings. Returns the new config.', {}, async () => {
|
|
63
|
+
const newConfig = loadConfig(configPath);
|
|
64
|
+
// Propagate to all managers
|
|
65
|
+
Object.assign(config, newConfig);
|
|
66
|
+
lifecycle.updateInstalledAgents(registry.getInstalled());
|
|
67
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
68
|
+
agent_servers: Object.keys(newConfig.agent_servers),
|
|
69
|
+
registries: newConfig.registries,
|
|
70
|
+
defaultPermissionPolicy: newConfig.defaultPermissionPolicy,
|
|
71
|
+
reloaded: true,
|
|
72
|
+
}, null, 2) }] };
|
|
73
|
+
});
|
|
74
|
+
// ---- Lifecycle tools ----
|
|
75
|
+
server.tool('initialize', 'Spawn an ACP agent process and perform the initialize handshake. Must be called before creating sessions.', {
|
|
76
|
+
agentId: z.string().describe('ID of the installed agent to initialize'),
|
|
77
|
+
protocolVersion: z.number().optional().describe('Protocol version to negotiate'),
|
|
78
|
+
clientInfo: z.object({
|
|
79
|
+
name: z.string(), version: z.string(), title: z.string().optional(),
|
|
80
|
+
}).optional().describe('Calling client info'),
|
|
81
|
+
clientCapabilities: z.object({
|
|
82
|
+
fs: z.object({
|
|
83
|
+
readTextFile: z.boolean().optional(), writeTextFile: z.boolean().optional(),
|
|
84
|
+
}).optional(),
|
|
85
|
+
terminal: z.boolean().optional(),
|
|
86
|
+
}).optional().describe('Client capabilities'),
|
|
87
|
+
}, async ({ agentId, protocolVersion, clientInfo, clientCapabilities }) => {
|
|
88
|
+
const result = await lifecycle.initialize(agentId, protocolVersion, clientInfo, clientCapabilities);
|
|
89
|
+
const handle = lifecycle.getAgent(agentId);
|
|
90
|
+
handle.transport.setRequestHandler(async (method, params) => {
|
|
91
|
+
if (method === 'session/request_permission') {
|
|
92
|
+
throw new Error('Permission requests should be handled during prompt');
|
|
93
|
+
}
|
|
94
|
+
return agentRequests.dispatch(method, params);
|
|
95
|
+
});
|
|
96
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
97
|
+
});
|
|
98
|
+
server.tool('shutdown', 'Gracefully shut down a running ACP agent, closing all sessions.', { agentId: z.string().describe('ID of the agent to shut down') }, async ({ agentId }) => {
|
|
99
|
+
sessions.closeAllForAgent(agentId);
|
|
100
|
+
promptHandler.onSessionRemoved();
|
|
101
|
+
await lifecycle.shutdown(agentId);
|
|
102
|
+
return { content: [{ type: 'text', text: `Shut down ${agentId}` }] };
|
|
103
|
+
});
|
|
104
|
+
// ---- Session tools ----
|
|
105
|
+
server.tool('new_session', "Create a new ACP session on an initialized agent. Returns the agent's session ID.", {
|
|
106
|
+
agentId: z.string().describe('ID of the initialized agent'),
|
|
107
|
+
cwd: z.string().describe('Working directory for the session'),
|
|
108
|
+
mcpServers: z.array(z.union([
|
|
109
|
+
z.object({ name: z.string(), command: z.string(), args: z.array(z.string()).optional() }),
|
|
110
|
+
z.object({ type: z.literal('http'), name: z.string(), url: z.string() }),
|
|
111
|
+
])).optional().describe('MCP servers to make available to the agent'),
|
|
112
|
+
permissionPolicy: z.enum(['elicit', 'allow_all', 'deny_all', 'operator']).optional()
|
|
113
|
+
.describe('Permission policy: elicit, allow_all, deny_all, or operator'),
|
|
114
|
+
}, async ({ agentId, cwd, mcpServers, permissionPolicy }) => {
|
|
115
|
+
const result = await sessions.newSession(agentId, cwd, mcpServers, permissionPolicy);
|
|
116
|
+
agentRequests.registerSession(result.sessionId, cwd);
|
|
117
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
118
|
+
});
|
|
119
|
+
server.tool('load_session', 'Resume a previously created session. Agent must support session loading.', {
|
|
120
|
+
agentId: z.string().describe('ID of the initialized agent'),
|
|
121
|
+
sessionId: z.string().describe('Session ID to resume'),
|
|
122
|
+
cwd: z.string().describe('Working directory'),
|
|
123
|
+
mcpServers: z.array(z.union([
|
|
124
|
+
z.object({ name: z.string(), command: z.string(), args: z.array(z.string()).optional() }),
|
|
125
|
+
z.object({ type: z.literal('http'), name: z.string(), url: z.string() }),
|
|
126
|
+
])).optional(),
|
|
127
|
+
}, async ({ agentId, sessionId, cwd, mcpServers }) => {
|
|
128
|
+
const result = await sessions.loadSession(agentId, sessionId, cwd, mcpServers);
|
|
129
|
+
agentRequests.registerSession(result.sessionId, cwd);
|
|
130
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
131
|
+
});
|
|
132
|
+
server.tool('list_sessions', 'List stored sessions. Does not require the agent to be running.', { agentId: z.string().describe('Agent ID to list sessions for') }, async ({ agentId }) => ({
|
|
133
|
+
content: [{ type: 'text', text: JSON.stringify(sessions.listSessions(agentId), null, 2) }],
|
|
134
|
+
}));
|
|
135
|
+
server.tool('close_session', 'Close an active session. Session file preserved for future load_session.', { sessionId: z.string().describe('Session ID to close') }, async ({ sessionId }) => {
|
|
136
|
+
agentRequests.unregisterSession(sessionId);
|
|
137
|
+
sessions.closeSession(sessionId);
|
|
138
|
+
promptHandler.onSessionRemoved();
|
|
139
|
+
return { content: [{ type: 'text', text: `Closed session ${sessionId}` }] };
|
|
140
|
+
});
|
|
141
|
+
// ---- Interaction tools ----
|
|
142
|
+
server.tool('prompt_start', 'Send a prompt to an active ACP session. Returns immediately with { status: "prompted" }. Use prompt or prompt_events to consume events.', {
|
|
143
|
+
sessionId: z.string().describe('Active session ID'),
|
|
144
|
+
prompt: z.union([
|
|
145
|
+
z.string(),
|
|
146
|
+
z.array(z.union([
|
|
147
|
+
z.object({ type: z.literal('text'), text: z.string() }),
|
|
148
|
+
z.object({ type: z.literal('resource_link'), uri: z.string(), mimeType: z.string().optional() }),
|
|
149
|
+
])),
|
|
150
|
+
]).describe('Prompt text or content blocks'),
|
|
151
|
+
}, async ({ sessionId, prompt: p }) => ({
|
|
152
|
+
content: [{ type: 'text', text: JSON.stringify(promptHandler.promptStart(sessionId, p), null, 2) }],
|
|
153
|
+
}));
|
|
154
|
+
server.tool('prompt_events', 'Non-blocking poll for prompt events. Returns all queued events (updates, permission requests, completion). May return empty array if no new events.', { sessionId: z.string().describe('Active session ID') }, async ({ sessionId }) => ({
|
|
155
|
+
content: [{ type: 'text', text: JSON.stringify(promptHandler.promptEvents(sessionId), null, 2) }],
|
|
156
|
+
}));
|
|
157
|
+
server.tool('prompt', 'Block until at least one prompt event is available. Returns queued events including updates (with full ACP metadata), permission requests, and completion. The default way to consume prompt results.', { sessionId: z.string().describe('Active session ID') }, async ({ sessionId }) => ({
|
|
158
|
+
content: [{ type: 'text', text: JSON.stringify(await promptHandler.prompt(sessionId), null, 2) }],
|
|
159
|
+
}));
|
|
160
|
+
server.tool('events', 'Block until any prompted session produces events. Returns events stamped with sessionId and agentId. Supports optional Nagle-style coalescing to batch events across sessions.', {
|
|
161
|
+
timeoutMs: z.number().optional().describe('Max wait time in ms. Returns empty on timeout.'),
|
|
162
|
+
nagleMs: z.number().optional().describe('Coalescing window in ms. Batches events arriving within this window. Default: 0 (immediate).'),
|
|
163
|
+
}, async ({ timeoutMs, nagleMs }) => ({
|
|
164
|
+
content: [{ type: 'text', text: JSON.stringify(await promptHandler.events(timeoutMs, nagleMs), null, 2) }],
|
|
165
|
+
}));
|
|
166
|
+
server.tool('grant_permission', 'Respond to a pending permission request (operator policy). The agent resumes; new events flow to the queue.', {
|
|
167
|
+
sessionId: z.string().describe('Session with pending permission'),
|
|
168
|
+
toolCallId: z.string().describe('Tool call ID requesting permission'),
|
|
169
|
+
optionId: z.string().describe('Permission option to select'),
|
|
170
|
+
}, async ({ sessionId, toolCallId, optionId }) => {
|
|
171
|
+
promptHandler.grantPermission(sessionId, toolCallId, optionId);
|
|
172
|
+
return { content: [{ type: 'text', text: `Permission granted: ${optionId}` }] };
|
|
173
|
+
});
|
|
174
|
+
server.tool('request_permission', 'Send an MCP elicitation to the outer host asking for a permission decision. Does not require a running agent or session.', {
|
|
175
|
+
title: z.string().describe('Human-readable description of the action requesting permission'),
|
|
176
|
+
options: z.array(z.object({
|
|
177
|
+
optionId: z.string(),
|
|
178
|
+
name: z.string(),
|
|
179
|
+
})).optional().describe('Permission choices (defaults to Allow / Reject)'),
|
|
180
|
+
}, async ({ title, options }) => {
|
|
181
|
+
const choices = options ?? [
|
|
182
|
+
{ optionId: 'allow', name: 'Allow' },
|
|
183
|
+
{ optionId: 'reject', name: 'Reject' },
|
|
184
|
+
];
|
|
185
|
+
const result = await server.server.elicitInput({
|
|
186
|
+
message: `Agent requests permission: ${title}`,
|
|
187
|
+
requestedSchema: {
|
|
188
|
+
type: 'object',
|
|
189
|
+
properties: {
|
|
190
|
+
decision: {
|
|
191
|
+
type: 'string',
|
|
192
|
+
title: 'Permission',
|
|
193
|
+
description: `Agent wants to: ${title}`,
|
|
194
|
+
enum: choices.map(o => o.optionId),
|
|
195
|
+
enumNames: choices.map(o => o.name),
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
required: ['decision'],
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
202
|
+
action: result.action,
|
|
203
|
+
decision: result.content?.decision ?? null,
|
|
204
|
+
}, null, 2) }] };
|
|
205
|
+
});
|
|
206
|
+
server.tool('cancel', 'Cancel an in-progress prompt.', { sessionId: z.string().describe('Session to cancel') }, async ({ sessionId }) => {
|
|
207
|
+
promptHandler.cancel(sessionId);
|
|
208
|
+
return { content: [{ type: 'text', text: `Cancelled prompt on ${sessionId}` }] };
|
|
209
|
+
});
|
|
210
|
+
server.tool('set_mode', 'Switch the operating mode of a session.', { sessionId: z.string().describe('Session ID'), modeId: z.string().describe('Mode to switch to') }, async ({ sessionId, modeId }) => {
|
|
211
|
+
await promptHandler.setMode(sessionId, modeId);
|
|
212
|
+
return { content: [{ type: 'text', text: `Switched to mode ${modeId}` }] };
|
|
213
|
+
});
|
|
214
|
+
// ---- Status tools ----
|
|
215
|
+
server.tool('list_running_agents', 'List all spawned ACP agent processes with status, heartbeat, and active sessions.', {}, async () => ({
|
|
216
|
+
content: [{ type: 'text', text: JSON.stringify(lifecycle.getAllAgents().map(h => ({
|
|
217
|
+
agentId: h.agentId, status: h.status.text, statusUpdatedAt: h.status.updatedAt,
|
|
218
|
+
startedAt: h.startedAt, lastActivityAt: h.lastActivityAt,
|
|
219
|
+
lastMessageAt: h.transport.lastMessageAt,
|
|
220
|
+
activeSessions: Array.from(h.activeSessions),
|
|
221
|
+
capabilities: h.capabilities, agentInfo: h.agentInfo,
|
|
222
|
+
})), null, 2) }],
|
|
223
|
+
}));
|
|
224
|
+
server.tool('get_agent_status', 'Get detailed status of a running ACP agent.', { agentId: z.string().describe('Agent to query') }, async ({ agentId }) => {
|
|
225
|
+
const h = lifecycle.getAgent(agentId);
|
|
226
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
227
|
+
agentId: h.agentId, status: h.status.text, statusUpdatedAt: h.status.updatedAt,
|
|
228
|
+
startedAt: h.startedAt, lastActivityAt: h.lastActivityAt,
|
|
229
|
+
lastMessageAt: h.transport.lastMessageAt, activeSessions: Array.from(h.activeSessions),
|
|
230
|
+
protocolVersion: h.protocolVersion, capabilities: h.capabilities, agentInfo: h.agentInfo,
|
|
231
|
+
}, null, 2) }] };
|
|
232
|
+
});
|
|
233
|
+
server.tool('set_agent_status', 'Set an explicit status text for a running agent.', { agentId: z.string().describe('Agent ID'), status: z.string().describe('Status text') }, async ({ agentId, status }) => {
|
|
234
|
+
lifecycle.getAgent(agentId).status = { text: status, updatedAt: Date.now() };
|
|
235
|
+
return { content: [{ type: 'text', text: `Status set for ${agentId}: ${status}` }] };
|
|
236
|
+
});
|
|
237
|
+
// ---- Resources ----
|
|
238
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
239
|
+
const __dirname = dirname(__filename);
|
|
240
|
+
const docsDir = resolve(__dirname, '../../docs');
|
|
241
|
+
server.resource('configuration-guide', 'docs://configuration.md', { description: 'MCACP configuration guide — config file locations, schema, permission policies, and editor import' }, async (uri) => ({
|
|
242
|
+
contents: [{
|
|
243
|
+
uri: uri.href,
|
|
244
|
+
mimeType: 'text/markdown',
|
|
245
|
+
text: readFileSync(resolve(docsDir, 'configuration.md'), 'utf-8'),
|
|
246
|
+
}],
|
|
247
|
+
}));
|
|
248
|
+
return {
|
|
249
|
+
server,
|
|
250
|
+
async start() {
|
|
251
|
+
const transport = new StdioServerTransport();
|
|
252
|
+
transport.onerror = (error) => {
|
|
253
|
+
if (error instanceof SyntaxError) {
|
|
254
|
+
// Not JSON — framing-level problem, other side isn't speaking the protocol
|
|
255
|
+
process.stderr.write(`[mcacp] Framing error: ${error.message}\n`);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// Valid JSON but not a valid JSON-RPC message
|
|
259
|
+
process.stderr.write(`[mcacp] Invalid JSON-RPC message: ${error.message}\n`);
|
|
260
|
+
process.stdout.write(JSON.stringify({
|
|
261
|
+
jsonrpc: '2.0',
|
|
262
|
+
id: null,
|
|
263
|
+
error: { code: -32700, message: 'Parse error', data: error.message },
|
|
264
|
+
}) + '\n');
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
await server.connect(transport);
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { McacpConfig, PermissionPolicy } from '../types/config.js';
|
|
2
|
+
import type { SessionId, SessionNewResult, SessionLoadResult, McpServer, SessionUpdate, StopReason } from '../types/acp.js';
|
|
3
|
+
import { LifecycleManager } from '../acp/lifecycle.js';
|
|
4
|
+
export interface SessionFile {
|
|
5
|
+
sessionId: SessionId;
|
|
6
|
+
agentId: string;
|
|
7
|
+
cwd: string;
|
|
8
|
+
permissionPolicy: PermissionPolicy;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
lastActiveAt: string;
|
|
11
|
+
closedAt?: string;
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export type PromptState = 'idle' | 'prompted';
|
|
15
|
+
export type BarePromptEvent = {
|
|
16
|
+
type: 'update';
|
|
17
|
+
update: SessionUpdate;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'permission_request';
|
|
20
|
+
toolCallId: string;
|
|
21
|
+
title: string;
|
|
22
|
+
options: Array<{
|
|
23
|
+
optionId: string;
|
|
24
|
+
name: string;
|
|
25
|
+
kind: string;
|
|
26
|
+
}>;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'complete';
|
|
29
|
+
stopReason: StopReason;
|
|
30
|
+
} | {
|
|
31
|
+
type: 'error';
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
export type PromptEvent = BarePromptEvent & {
|
|
35
|
+
sessionId: SessionId;
|
|
36
|
+
agentId: string;
|
|
37
|
+
};
|
|
38
|
+
export interface ActiveSession {
|
|
39
|
+
sessionId: SessionId;
|
|
40
|
+
agentId: string;
|
|
41
|
+
permissionPolicy: PermissionPolicy;
|
|
42
|
+
pendingPermission: PendingPermission | null;
|
|
43
|
+
promptState: PromptState;
|
|
44
|
+
eventQueue: PromptEvent[];
|
|
45
|
+
waiters: Array<(events: PromptEvent[]) => void>;
|
|
46
|
+
/** Accumulated text for Nagle-style chunk consolidation */
|
|
47
|
+
chunkBuffer: {
|
|
48
|
+
text: string;
|
|
49
|
+
updateType: string;
|
|
50
|
+
} | null;
|
|
51
|
+
/** Pending flush timer for chunk consolidation */
|
|
52
|
+
chunkTimer: ReturnType<typeof setTimeout> | null;
|
|
53
|
+
}
|
|
54
|
+
export interface PendingPermission {
|
|
55
|
+
toolCallId: string;
|
|
56
|
+
title: string;
|
|
57
|
+
options: Array<{
|
|
58
|
+
optionId: string;
|
|
59
|
+
name: string;
|
|
60
|
+
kind: string;
|
|
61
|
+
}>;
|
|
62
|
+
resolve: (outcome: {
|
|
63
|
+
selected: {
|
|
64
|
+
optionId: string;
|
|
65
|
+
};
|
|
66
|
+
} | {
|
|
67
|
+
cancelled: Record<string, never>;
|
|
68
|
+
}) => void;
|
|
69
|
+
}
|
|
70
|
+
export declare class SessionManager {
|
|
71
|
+
private config;
|
|
72
|
+
private lifecycle;
|
|
73
|
+
private activeSessions;
|
|
74
|
+
constructor(config: McacpConfig, lifecycle: LifecycleManager);
|
|
75
|
+
newSession(agentId: string, cwd: string, mcpServers?: McpServer[], permissionPolicy?: PermissionPolicy): Promise<{
|
|
76
|
+
sessionId: SessionId;
|
|
77
|
+
modes?: SessionNewResult['modes'];
|
|
78
|
+
}>;
|
|
79
|
+
loadSession(agentId: string, sessionId: SessionId, cwd: string, mcpServers?: McpServer[]): Promise<{
|
|
80
|
+
sessionId: SessionId;
|
|
81
|
+
modes?: SessionLoadResult['modes'];
|
|
82
|
+
}>;
|
|
83
|
+
listSessions(agentId: string): SessionFile[];
|
|
84
|
+
closeSession(sessionId: SessionId): void;
|
|
85
|
+
getSession(sessionId: SessionId): ActiveSession;
|
|
86
|
+
touchSession(sessionId: SessionId): void;
|
|
87
|
+
closeAllForAgent(agentId: string): void;
|
|
88
|
+
private sessionFilePath;
|
|
89
|
+
private saveSessionFile;
|
|
90
|
+
private readSessionFile;
|
|
91
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { resolve, join, sep, dirname } from 'node:path';
|
|
3
|
+
export class SessionManager {
|
|
4
|
+
config;
|
|
5
|
+
lifecycle;
|
|
6
|
+
activeSessions = new Map();
|
|
7
|
+
constructor(config, lifecycle) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
this.lifecycle = lifecycle;
|
|
10
|
+
}
|
|
11
|
+
async newSession(agentId, cwd, mcpServers, permissionPolicy) {
|
|
12
|
+
const handle = this.lifecycle.getAgent(agentId);
|
|
13
|
+
const policy = permissionPolicy ?? this.config.defaultPermissionPolicy;
|
|
14
|
+
const result = await handle.transport.request('session/new', {
|
|
15
|
+
cwd, mcpServers: mcpServers ?? [],
|
|
16
|
+
});
|
|
17
|
+
this.activeSessions.set(result.sessionId, {
|
|
18
|
+
sessionId: result.sessionId, agentId, permissionPolicy: policy, pendingPermission: null,
|
|
19
|
+
promptState: 'idle', eventQueue: [], waiters: [],
|
|
20
|
+
chunkBuffer: null, chunkTimer: null,
|
|
21
|
+
});
|
|
22
|
+
handle.activeSessions.add(result.sessionId);
|
|
23
|
+
this.saveSessionFile({
|
|
24
|
+
sessionId: result.sessionId, agentId, cwd, permissionPolicy: policy,
|
|
25
|
+
createdAt: new Date().toISOString(), lastActiveAt: new Date().toISOString(),
|
|
26
|
+
});
|
|
27
|
+
this.lifecycle.touchActivity(agentId);
|
|
28
|
+
return { sessionId: result.sessionId, modes: result.modes };
|
|
29
|
+
}
|
|
30
|
+
async loadSession(agentId, sessionId, cwd, mcpServers) {
|
|
31
|
+
const handle = this.lifecycle.getAgent(agentId);
|
|
32
|
+
if (!handle.capabilities.loadSession) {
|
|
33
|
+
throw new Error(`Agent "${agentId}" does not support loading sessions`);
|
|
34
|
+
}
|
|
35
|
+
const result = await handle.transport.request('session/load', {
|
|
36
|
+
sessionId, cwd, mcpServers: mcpServers ?? [],
|
|
37
|
+
});
|
|
38
|
+
const file = this.readSessionFile(agentId, sessionId);
|
|
39
|
+
const policy = file?.permissionPolicy ?? this.config.defaultPermissionPolicy;
|
|
40
|
+
this.activeSessions.set(sessionId, {
|
|
41
|
+
sessionId, agentId, permissionPolicy: policy, pendingPermission: null,
|
|
42
|
+
promptState: 'idle', eventQueue: [], waiters: [],
|
|
43
|
+
chunkBuffer: null, chunkTimer: null,
|
|
44
|
+
});
|
|
45
|
+
handle.activeSessions.add(sessionId);
|
|
46
|
+
this.saveSessionFile({
|
|
47
|
+
sessionId, agentId, cwd, permissionPolicy: policy,
|
|
48
|
+
createdAt: file?.createdAt ?? new Date().toISOString(),
|
|
49
|
+
lastActiveAt: new Date().toISOString(),
|
|
50
|
+
});
|
|
51
|
+
this.lifecycle.touchActivity(agentId);
|
|
52
|
+
return { sessionId, modes: result.modes };
|
|
53
|
+
}
|
|
54
|
+
listSessions(agentId) {
|
|
55
|
+
const safeAgentId = agentId.replace(/[^a-zA-Z0-9._@\/-]/g, '_');
|
|
56
|
+
const sessionsDir = resolve(this.config.sessionDir, safeAgentId, 'sessions');
|
|
57
|
+
if (!existsSync(sessionsDir))
|
|
58
|
+
return [];
|
|
59
|
+
const results = [];
|
|
60
|
+
try {
|
|
61
|
+
for (const f of readdirSync(sessionsDir).filter(f => f.endsWith('.json'))) {
|
|
62
|
+
try {
|
|
63
|
+
results.push(JSON.parse(readFileSync(join(sessionsDir, f), 'utf-8')));
|
|
64
|
+
}
|
|
65
|
+
catch { }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch { }
|
|
69
|
+
return results;
|
|
70
|
+
}
|
|
71
|
+
closeSession(sessionId) {
|
|
72
|
+
const session = this.activeSessions.get(sessionId);
|
|
73
|
+
if (!session)
|
|
74
|
+
throw new Error(`Session "${sessionId}" is not active`);
|
|
75
|
+
const handle = this.lifecycle.getAgent(session.agentId);
|
|
76
|
+
handle.activeSessions.delete(sessionId);
|
|
77
|
+
this.activeSessions.delete(sessionId);
|
|
78
|
+
const file = this.readSessionFile(session.agentId, sessionId);
|
|
79
|
+
if (file) {
|
|
80
|
+
file.closedAt = new Date().toISOString();
|
|
81
|
+
file.lastActiveAt = new Date().toISOString();
|
|
82
|
+
this.saveSessionFile(file);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
getSession(sessionId) {
|
|
86
|
+
const session = this.activeSessions.get(sessionId);
|
|
87
|
+
if (!session)
|
|
88
|
+
throw new Error(`Session "${sessionId}" is not active`);
|
|
89
|
+
return session;
|
|
90
|
+
}
|
|
91
|
+
touchSession(sessionId) {
|
|
92
|
+
const session = this.activeSessions.get(sessionId);
|
|
93
|
+
if (!session)
|
|
94
|
+
return;
|
|
95
|
+
const file = this.readSessionFile(session.agentId, sessionId);
|
|
96
|
+
if (file) {
|
|
97
|
+
file.lastActiveAt = new Date().toISOString();
|
|
98
|
+
this.saveSessionFile(file);
|
|
99
|
+
}
|
|
100
|
+
this.lifecycle.touchActivity(session.agentId);
|
|
101
|
+
}
|
|
102
|
+
closeAllForAgent(agentId) {
|
|
103
|
+
for (const [id, session] of this.activeSessions) {
|
|
104
|
+
if (session.agentId === agentId) {
|
|
105
|
+
this.activeSessions.delete(id);
|
|
106
|
+
// Mark session file as closed
|
|
107
|
+
const file = this.readSessionFile(agentId, id);
|
|
108
|
+
if (file) {
|
|
109
|
+
file.closedAt = new Date().toISOString();
|
|
110
|
+
file.lastActiveAt = new Date().toISOString();
|
|
111
|
+
this.saveSessionFile(file);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Also clean up on the agent handle
|
|
116
|
+
try {
|
|
117
|
+
const handle = this.lifecycle.getAgent(agentId);
|
|
118
|
+
handle.activeSessions.clear();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Agent may already be shut down
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
sessionFilePath(agentId, sessionId) {
|
|
125
|
+
const safeAgentId = agentId.replace(/[^a-zA-Z0-9._@\/-]/g, '_');
|
|
126
|
+
const safeSessionId = sessionId.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
127
|
+
const filePath = resolve(this.config.sessionDir, safeAgentId, 'sessions', `${safeSessionId}.json`);
|
|
128
|
+
const sessionRoot = resolve(this.config.sessionDir);
|
|
129
|
+
if (!filePath.startsWith(sessionRoot + sep)) {
|
|
130
|
+
throw new Error('Invalid agentId or sessionId: path traversal detected');
|
|
131
|
+
}
|
|
132
|
+
return filePath;
|
|
133
|
+
}
|
|
134
|
+
saveSessionFile(file) {
|
|
135
|
+
const filePath = this.sessionFilePath(file.agentId, file.sessionId);
|
|
136
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
137
|
+
writeFileSync(filePath, JSON.stringify(file, null, 2));
|
|
138
|
+
}
|
|
139
|
+
readSessionFile(agentId, sessionId) {
|
|
140
|
+
const path = this.sessionFilePath(agentId, sessionId);
|
|
141
|
+
if (!existsSync(path))
|
|
142
|
+
return null;
|
|
143
|
+
try {
|
|
144
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sessions/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { SessionId, ContentBlock } from '../types/acp.js';
|
|
2
|
+
import type { McacpConfig } from '../types/config.js';
|
|
3
|
+
import type { PromptEvent } from './index.js';
|
|
4
|
+
import { LifecycleManager } from '../acp/lifecycle.js';
|
|
5
|
+
import { SessionManager } from './index.js';
|
|
6
|
+
import { PermissionEngine } from '../permissions/index.js';
|
|
7
|
+
export declare class PromptHandler {
|
|
8
|
+
private lifecycle;
|
|
9
|
+
private sessions;
|
|
10
|
+
private permissions;
|
|
11
|
+
private config;
|
|
12
|
+
private dispatchers;
|
|
13
|
+
private globalWaiter;
|
|
14
|
+
constructor(lifecycle: LifecycleManager, sessions: SessionManager, permissions: PermissionEngine, config: McacpConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Send a prompt to an ACP session. Returns immediately after dispatching.
|
|
17
|
+
* The session enters "prompted" state; use prompt_events or prompt to consume events.
|
|
18
|
+
*/
|
|
19
|
+
promptStart(sessionId: SessionId, promptContent: string | ContentBlock[]): {
|
|
20
|
+
status: 'prompted';
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Non-blocking poll. Returns all queued events (may be empty).
|
|
24
|
+
*/
|
|
25
|
+
promptEvents(sessionId: SessionId): {
|
|
26
|
+
events: PromptEvent[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Blocking wait. Returns when at least one event is available.
|
|
30
|
+
* If the queue already has events, returns immediately.
|
|
31
|
+
*/
|
|
32
|
+
prompt(sessionId: SessionId): Promise<{
|
|
33
|
+
events: PromptEvent[];
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Grant a pending operator permission. The agent resumes and new events
|
|
37
|
+
* continue flowing into the queue.
|
|
38
|
+
*/
|
|
39
|
+
grantPermission(sessionId: SessionId, toolCallId: string, optionId: string): void;
|
|
40
|
+
cancel(sessionId: SessionId): void;
|
|
41
|
+
setMode(sessionId: SessionId, modeId: string): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Block until any prompted session produces events. Returns events stamped
|
|
44
|
+
* with sessionId and agentId. Supports optional Nagle-style coalescing.
|
|
45
|
+
*/
|
|
46
|
+
events(timeoutMs?: number, nagleMs?: number): Promise<{
|
|
47
|
+
events: PromptEvent[];
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Cleanup hook: if no prompted sessions remain, resolve the global waiter
|
|
51
|
+
* with whatever events have been collected.
|
|
52
|
+
*/
|
|
53
|
+
onSessionRemoved(): void;
|
|
54
|
+
private notifyGlobalWaiter;
|
|
55
|
+
private flushGlobalWaiter;
|
|
56
|
+
/**
|
|
57
|
+
* Ensure the agent has a central dispatch handler installed, and register
|
|
58
|
+
* the session in its dispatch table.
|
|
59
|
+
*/
|
|
60
|
+
private ensureDispatcher;
|
|
61
|
+
/**
|
|
62
|
+
* Remove a session from the dispatch table. If no sessions remain,
|
|
63
|
+
* restore the original handlers and tear down the dispatcher.
|
|
64
|
+
*/
|
|
65
|
+
private unregisterSession;
|
|
66
|
+
/**
|
|
67
|
+
* Nagle-style consolidation: buffer text chunk events and flush as batches.
|
|
68
|
+
* Non-chunk events flush any pending buffer first, then push immediately.
|
|
69
|
+
*/
|
|
70
|
+
private pushEventConsolidated;
|
|
71
|
+
/** Flush the accumulated chunk buffer as a single consolidated update event. */
|
|
72
|
+
private flushChunkBuffer;
|
|
73
|
+
/** Reset chunk buffer state (called at prompt start). */
|
|
74
|
+
private resetChunkBuffer;
|
|
75
|
+
private pushEvent;
|
|
76
|
+
private handleOperatorPermission;
|
|
77
|
+
private updateAgentStatus;
|
|
78
|
+
}
|