@amodalai/runtime 0.1.15 → 0.1.17
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/src/agent/agent-runner.js +13 -1
- package/dist/src/agent/agent-runner.js.map +1 -1
- package/dist/src/agent/config-watcher.d.ts +2 -2
- package/dist/src/agent/config-watcher.js +28 -15
- package/dist/src/agent/config-watcher.js.map +1 -1
- package/dist/src/agent/config-watcher.test.js +13 -4
- package/dist/src/agent/config-watcher.test.js.map +1 -1
- package/dist/src/agent/eval-store.d.ts +14 -0
- package/dist/src/agent/eval-store.js +44 -0
- package/dist/src/agent/eval-store.js.map +1 -1
- package/dist/src/agent/feedback-store.d.ts +39 -0
- package/dist/src/agent/feedback-store.js +98 -0
- package/dist/src/agent/feedback-store.js.map +1 -0
- package/dist/src/agent/local-server.d.ts +1 -1
- package/dist/src/agent/local-server.js +48 -28
- package/dist/src/agent/local-server.js.map +1 -1
- package/dist/src/agent/local-server.test.js +2 -1
- package/dist/src/agent/local-server.test.js.map +1 -1
- package/dist/src/agent/proactive/proactive-runner.d.ts +3 -3
- package/dist/src/agent/proactive/proactive-runner.js +3 -3
- package/dist/src/agent/proactive/proactive-runner.js.map +1 -1
- package/dist/src/agent/proactive/proactive-runner.test.js +2 -2
- package/dist/src/agent/proactive/proactive-runner.test.js.map +1 -1
- package/dist/src/agent/routes/admin-chat.d.ts +3 -2
- package/dist/src/agent/routes/admin-chat.js +3 -3
- package/dist/src/agent/routes/admin-chat.js.map +1 -1
- package/dist/src/agent/routes/chat.d.ts +6 -6
- package/dist/src/agent/routes/chat.js +3 -3
- package/dist/src/agent/routes/chat.js.map +1 -1
- package/dist/src/agent/routes/chat.test.js +7 -6
- package/dist/src/agent/routes/chat.test.js.map +1 -1
- package/dist/src/agent/routes/evals.d.ts +2 -2
- package/dist/src/agent/routes/evals.js +143 -68
- package/dist/src/agent/routes/evals.js.map +1 -1
- package/dist/src/agent/routes/feedback.d.ts +11 -0
- package/dist/src/agent/routes/feedback.js +72 -0
- package/dist/src/agent/routes/feedback.js.map +1 -0
- package/dist/src/agent/routes/files.js +118 -12
- package/dist/src/agent/routes/files.js.map +1 -1
- package/dist/src/agent/routes/inspect.d.ts +2 -2
- package/dist/src/agent/routes/inspect.js +44 -22
- package/dist/src/agent/routes/inspect.js.map +1 -1
- package/dist/src/agent/routes/inspect.test.js +11 -16
- package/dist/src/agent/routes/inspect.test.js.map +1 -1
- package/dist/src/agent/routes/task.d.ts +2 -2
- package/dist/src/agent/routes/task.js +4 -4
- package/dist/src/agent/routes/task.js.map +1 -1
- package/dist/src/agent/routes/task.test.js.map +1 -1
- package/dist/src/agent/session-store.d.ts +2 -2
- package/dist/src/agent/session-store.js +9 -6
- package/dist/src/agent/session-store.js.map +1 -1
- package/dist/src/agent/snapshot-server.js +10 -2
- package/dist/src/agent/snapshot-server.js.map +1 -1
- package/dist/src/cron/heartbeat-runner.d.ts +3 -6
- package/dist/src/cron/heartbeat-runner.js +1 -10
- package/dist/src/cron/heartbeat-runner.js.map +1 -1
- package/dist/src/index.d.ts +5 -3
- package/dist/src/index.js +4 -9
- package/dist/src/index.js.map +1 -1
- package/dist/src/middleware/auth.d.ts +3 -19
- package/dist/src/middleware/auth.js +0 -118
- package/dist/src/middleware/auth.js.map +1 -1
- package/dist/src/routes/ai-stream.d.ts +8 -7
- package/dist/src/routes/ai-stream.js +3 -16
- package/dist/src/routes/ai-stream.js.map +1 -1
- package/dist/src/routes/chat-stream.d.ts +4 -3
- package/dist/src/routes/chat-stream.js +5 -17
- package/dist/src/routes/chat-stream.js.map +1 -1
- package/dist/src/routes/chat.d.ts +4 -2
- package/dist/src/routes/chat.js +2 -14
- package/dist/src/routes/chat.js.map +1 -1
- package/dist/src/routes/chat.test.js +2 -2
- package/dist/src/routes/chat.test.js.map +1 -1
- package/dist/src/server.d.ts +16 -3
- package/dist/src/server.js +24 -27
- package/dist/src/server.js.map +1 -1
- package/dist/src/server.test.js +37 -6
- package/dist/src/server.test.js.map +1 -1
- package/dist/src/session/admin-file-tools.d.ts +136 -0
- package/dist/src/session/admin-file-tools.js +240 -0
- package/dist/src/session/admin-file-tools.js.map +1 -0
- package/dist/src/session/custom-tool-adapter.d.ts +74 -0
- package/dist/src/session/custom-tool-adapter.js +149 -0
- package/dist/src/session/custom-tool-adapter.js.map +1 -0
- package/dist/src/session/session-manager.d.ts +101 -3
- package/dist/src/session/session-manager.js +467 -31
- package/dist/src/session/session-manager.js.map +1 -1
- package/dist/src/session/session-manager.test.js +93 -58
- package/dist/src/session/session-manager.test.js.map +1 -1
- package/dist/src/session/session-runner.d.ts +29 -13
- package/dist/src/session/session-runner.js +40 -91
- package/dist/src/session/session-runner.js.map +1 -1
- package/dist/src/session/session-runner.test.js +70 -80
- package/dist/src/session/session-runner.test.js.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist/src/agent/agent-runner.test.d.ts +0 -6
- package/dist/src/agent/agent-runner.test.js +0 -552
- package/dist/src/agent/agent-runner.test.js.map +0 -1
- package/dist/src/agent/session-manager.d.ts +0 -88
- package/dist/src/agent/session-manager.js +0 -341
- package/dist/src/agent/session-manager.js.map +0 -1
- package/dist/src/agent/session-manager.test.d.ts +0 -6
- package/dist/src/agent/session-manager.test.js +0 -145
- package/dist/src/agent/session-manager.test.js.map +0 -1
- package/dist/src/audit/audit-client.d.ts +0 -46
- package/dist/src/audit/audit-client.js +0 -83
- package/dist/src/audit/audit-client.js.map +0 -1
- package/dist/src/middleware/auth.test.d.ts +0 -6
- package/dist/src/middleware/auth.test.js +0 -260
- package/dist/src/middleware/auth.test.js.map +0 -1
- package/dist/src/routes/sessions.d.ts +0 -14
- package/dist/src/routes/sessions.js +0 -82
- package/dist/src/routes/sessions.js.map +0 -1
- package/dist/src/utils/jwt-verify.d.ts +0 -19
- package/dist/src/utils/jwt-verify.js +0 -32
- package/dist/src/utils/jwt-verify.js.map +0 -1
- package/dist/src/utils/jwt-verify.test.d.ts +0 -6
- package/dist/src/utils/jwt-verify.test.js +0 -150
- package/dist/src/utils/jwt-verify.test.js.map +0 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Admin-only file tools for reading, writing, and deleting agent config files.
|
|
8
|
+
* These tools are registered on admin sessions only, and only for local repos.
|
|
9
|
+
*
|
|
10
|
+
* Ported from the old agent-runner.ts admin tool implementation.
|
|
11
|
+
*/
|
|
12
|
+
import { readFile, writeFile, unlink, mkdir } from 'node:fs/promises';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Path validation
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
const ALLOWED_REPO_DIRS = [
|
|
18
|
+
'skills/',
|
|
19
|
+
'knowledge/',
|
|
20
|
+
'connections/',
|
|
21
|
+
'stores/',
|
|
22
|
+
'pages/',
|
|
23
|
+
'automations/',
|
|
24
|
+
'evals/',
|
|
25
|
+
'agents/',
|
|
26
|
+
'tools/',
|
|
27
|
+
'amodal_packages/', // installed packages (read-only)
|
|
28
|
+
];
|
|
29
|
+
const BLOCKED_FILENAMES = [
|
|
30
|
+
'.env',
|
|
31
|
+
'amodal.json',
|
|
32
|
+
'package.json',
|
|
33
|
+
'pnpm-lock.yaml',
|
|
34
|
+
'tsconfig.json',
|
|
35
|
+
];
|
|
36
|
+
const READ_ONLY_DIRS = [
|
|
37
|
+
'amodal_packages/',
|
|
38
|
+
];
|
|
39
|
+
/** @internal Exported for testing */
|
|
40
|
+
export function isAllowedRepoPath(relPath) {
|
|
41
|
+
const basename = path.basename(relPath);
|
|
42
|
+
if (BLOCKED_FILENAMES.includes(basename))
|
|
43
|
+
return false;
|
|
44
|
+
return ALLOWED_REPO_DIRS.some((dir) => relPath.startsWith(dir));
|
|
45
|
+
}
|
|
46
|
+
function isReadOnlyPath(relPath) {
|
|
47
|
+
return READ_ONLY_DIRS.some((dir) => relPath.startsWith(dir));
|
|
48
|
+
}
|
|
49
|
+
function validatePath(repoRoot, rawPath) {
|
|
50
|
+
if (!rawPath || rawPath.startsWith('/')) {
|
|
51
|
+
return { error: 'Path must be relative to the repo root (no leading /)' };
|
|
52
|
+
}
|
|
53
|
+
if (rawPath.includes('..')) {
|
|
54
|
+
return { error: 'Path traversal (..) is not allowed' };
|
|
55
|
+
}
|
|
56
|
+
const normalized = path.normalize(rawPath);
|
|
57
|
+
if (!isAllowedRepoPath(normalized)) {
|
|
58
|
+
return { error: `Path "${normalized}" is not in an allowed directory. Allowed: ${ALLOWED_REPO_DIRS.join(', ')}. Blocked files: ${BLOCKED_FILENAMES.join(', ')}` };
|
|
59
|
+
}
|
|
60
|
+
const resolved = path.resolve(repoRoot, normalized);
|
|
61
|
+
if (!resolved.startsWith(repoRoot)) {
|
|
62
|
+
return { error: 'Resolved path escapes the repo directory' };
|
|
63
|
+
}
|
|
64
|
+
return { resolved, relative: normalized };
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Base adapter matching upstream DeclarativeTool interface
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
function createToolAdapter(opts) {
|
|
70
|
+
return {
|
|
71
|
+
name: opts.name,
|
|
72
|
+
displayName: opts.name,
|
|
73
|
+
description: opts.description,
|
|
74
|
+
kind: 'declarative',
|
|
75
|
+
parameterSchema: opts.parameters,
|
|
76
|
+
get isReadOnly() { return opts.name === 'read_repo_file'; },
|
|
77
|
+
get toolAnnotations() { return undefined; },
|
|
78
|
+
get schema() { return this.getSchema(); },
|
|
79
|
+
getSchema() {
|
|
80
|
+
return {
|
|
81
|
+
name: opts.name,
|
|
82
|
+
description: opts.description,
|
|
83
|
+
parametersJsonSchema: opts.parameters,
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
build(params) {
|
|
87
|
+
return {
|
|
88
|
+
name: opts.name,
|
|
89
|
+
params,
|
|
90
|
+
execute: async () => opts.execute(params),
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
silentBuild(params) {
|
|
94
|
+
return this.build(params);
|
|
95
|
+
},
|
|
96
|
+
async validateBuildAndExecute(params) {
|
|
97
|
+
return opts.execute(params);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Tool factories
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
export function createReadRepoFileTool(repoRoot) {
|
|
105
|
+
return createToolAdapter({
|
|
106
|
+
name: 'read_repo_file',
|
|
107
|
+
description: 'Read a file from the agent repo. Path is relative to repo root. Allowed directories: skills/, knowledge/, connections/, stores/, pages/, automations/, evals/, agents/, tools/.',
|
|
108
|
+
parameters: {
|
|
109
|
+
type: 'object',
|
|
110
|
+
properties: {
|
|
111
|
+
path: { type: 'string', description: 'File path relative to repo root (e.g. "knowledge/formatting-rules.md")' },
|
|
112
|
+
},
|
|
113
|
+
required: ['path'],
|
|
114
|
+
},
|
|
115
|
+
async execute(params) {
|
|
116
|
+
const rawPath = String(params['path'] ?? '');
|
|
117
|
+
const validation = validatePath(repoRoot, rawPath);
|
|
118
|
+
if ('error' in validation) {
|
|
119
|
+
return { llmContent: `Error: ${validation.error}`, error: { message: validation.error, type: 'VALIDATION_ERROR' } };
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const content = await readFile(validation.resolved, 'utf-8');
|
|
123
|
+
return { llmContent: content, returnDisplay: `Read ${validation.relative}` };
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const isNotFound = err instanceof Error && 'code' in err && (err.code) === 'ENOENT'; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion -- checking errno;
|
|
127
|
+
const msg = isNotFound ? `File not found: ${validation.relative}` : (err instanceof Error ? err.message : String(err));
|
|
128
|
+
return { llmContent: `Error: ${msg}`, error: { message: msg, type: 'EXECUTION_FAILED' } };
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
export function createWriteRepoFileTool(repoRoot) {
|
|
134
|
+
return createToolAdapter({
|
|
135
|
+
name: 'write_repo_file',
|
|
136
|
+
description: 'Create or update a file in the agent repo. Use this to add skills, knowledge, pages, automations, tools, store schemas, evals, connection docs, or agent overrides. Path is relative to repo root. Allowed directories: skills/, knowledge/, connections/, stores/, pages/, automations/, evals/, agents/, tools/.',
|
|
137
|
+
parameters: {
|
|
138
|
+
type: 'object',
|
|
139
|
+
properties: {
|
|
140
|
+
path: { type: 'string', description: 'File path relative to repo root (e.g. "knowledge/formatting-rules.md")' },
|
|
141
|
+
content: { type: 'string', description: 'Full file content to write' },
|
|
142
|
+
},
|
|
143
|
+
required: ['path', 'content'],
|
|
144
|
+
},
|
|
145
|
+
async execute(params) {
|
|
146
|
+
const rawPath = String(params['path'] ?? '');
|
|
147
|
+
const content = String(params['content'] ?? '');
|
|
148
|
+
const validation = validatePath(repoRoot, rawPath);
|
|
149
|
+
if ('error' in validation) {
|
|
150
|
+
return { llmContent: `Error: ${validation.error}`, error: { message: validation.error, type: 'VALIDATION_ERROR' } };
|
|
151
|
+
}
|
|
152
|
+
if (isReadOnlyPath(validation.relative)) {
|
|
153
|
+
return { llmContent: `Error: ${validation.relative} is read-only (installed package)`, error: { message: 'Cannot write to installed packages', type: 'VALIDATION_ERROR' } };
|
|
154
|
+
}
|
|
155
|
+
if (!content) {
|
|
156
|
+
return { llmContent: 'Error: Content must not be empty', error: { message: 'Content must not be empty', type: 'VALIDATION_ERROR' } };
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
await mkdir(path.dirname(validation.resolved), { recursive: true });
|
|
160
|
+
await writeFile(validation.resolved, content, 'utf-8');
|
|
161
|
+
return { llmContent: `Wrote ${validation.relative} (${String(content.length)} bytes)`, returnDisplay: `Wrote ${validation.relative}` };
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
165
|
+
return { llmContent: `Error: ${msg}`, error: { message: msg, type: 'EXECUTION_FAILED' } };
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
export function createDeleteRepoFileTool(repoRoot) {
|
|
171
|
+
return createToolAdapter({
|
|
172
|
+
name: 'delete_repo_file',
|
|
173
|
+
description: 'Delete a file from the agent repo. Always confirm with the user before deleting. Path is relative to repo root. Same directory restrictions as write_repo_file.',
|
|
174
|
+
parameters: {
|
|
175
|
+
type: 'object',
|
|
176
|
+
properties: {
|
|
177
|
+
path: { type: 'string', description: 'File path relative to repo root (e.g. "evals/old-test.md")' },
|
|
178
|
+
},
|
|
179
|
+
required: ['path'],
|
|
180
|
+
},
|
|
181
|
+
async execute(params) {
|
|
182
|
+
const rawPath = String(params['path'] ?? '');
|
|
183
|
+
const validation = validatePath(repoRoot, rawPath);
|
|
184
|
+
if ('error' in validation) {
|
|
185
|
+
return { llmContent: `Error: ${validation.error}`, error: { message: validation.error, type: 'VALIDATION_ERROR' } };
|
|
186
|
+
}
|
|
187
|
+
if (isReadOnlyPath(validation.relative)) {
|
|
188
|
+
return { llmContent: `Error: ${validation.relative} is read-only (installed package)`, error: { message: 'Cannot delete installed packages', type: 'VALIDATION_ERROR' } };
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
await unlink(validation.resolved);
|
|
192
|
+
return { llmContent: `Deleted ${validation.relative}`, returnDisplay: `Deleted ${validation.relative}` };
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
const isNotFound = err instanceof Error && 'code' in err && (err.code) === 'ENOENT'; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion -- checking errno;
|
|
196
|
+
const msg = isNotFound ? `File not found: ${validation.relative}` : (err instanceof Error ? err.message : String(err));
|
|
197
|
+
return { llmContent: `Error: ${msg}`, error: { message: msg, type: 'EXECUTION_FAILED' } };
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
// Internal API tool — lets admin query the local runtime's own endpoints
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
export function createInternalApiTool(getPort) {
|
|
206
|
+
return createToolAdapter({
|
|
207
|
+
name: 'internal_api',
|
|
208
|
+
description: `Query the amodal runtime's internal API. Use this to check eval results, connection health, agent context, store data, and automation status. The endpoint is relative to the local server (e.g. "/api/evals/runs" or "/inspect/health"). Only GET requests are supported.`,
|
|
209
|
+
parameters: {
|
|
210
|
+
type: 'object',
|
|
211
|
+
properties: {
|
|
212
|
+
endpoint: { type: 'string', description: 'API path (e.g. "/api/evals/runs", "/inspect/health", "/api/stores")' },
|
|
213
|
+
},
|
|
214
|
+
required: ['endpoint'],
|
|
215
|
+
},
|
|
216
|
+
async execute(params) {
|
|
217
|
+
const endpoint = String(params['endpoint'] ?? '');
|
|
218
|
+
const port = getPort();
|
|
219
|
+
if (!port) {
|
|
220
|
+
return { llmContent: 'Error: Server not ready', error: { message: 'Server not ready', type: 'EXECUTION_FAILED' } };
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const resp = await fetch(`http://127.0.0.1:${port}${endpoint}`);
|
|
224
|
+
const text = await resp.text();
|
|
225
|
+
try {
|
|
226
|
+
const json = JSON.parse(text);
|
|
227
|
+
return { llmContent: JSON.stringify(json, null, 2), returnDisplay: `GET ${endpoint} → ${resp.status}` };
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return { llmContent: text, returnDisplay: `GET ${endpoint} → ${resp.status}` };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
235
|
+
return { llmContent: `Error: ${msg}`, error: { message: msg, type: 'EXECUTION_FAILED' } };
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=admin-file-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-file-tools.js","sourceRoot":"","sources":["../../../src/session/admin-file-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import type { LoadedTool, CustomToolExecutor } from '@amodalai/core';
|
|
7
|
+
import type { ManagedSession } from './session-manager.js';
|
|
8
|
+
/**
|
|
9
|
+
* Adapts a repo LoadedTool to the upstream tool registry interface.
|
|
10
|
+
* Wraps the tool definition and delegates execution to the CustomToolExecutor.
|
|
11
|
+
*/
|
|
12
|
+
export declare class CustomToolAdapter {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly displayName: string;
|
|
15
|
+
private readonly tool;
|
|
16
|
+
private readonly session;
|
|
17
|
+
private readonly executor;
|
|
18
|
+
readonly kind: "declarative";
|
|
19
|
+
readonly description: string;
|
|
20
|
+
readonly parameterSchema: Record<string, unknown>;
|
|
21
|
+
constructor(tool: LoadedTool, session: ManagedSession, executor: CustomToolExecutor);
|
|
22
|
+
get isReadOnly(): boolean;
|
|
23
|
+
get toolAnnotations(): undefined;
|
|
24
|
+
getSchema(_modelId?: string): {
|
|
25
|
+
name: string;
|
|
26
|
+
description: string;
|
|
27
|
+
parametersJsonSchema: Record<string, unknown>;
|
|
28
|
+
};
|
|
29
|
+
get schema(): {
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
parametersJsonSchema: Record<string, unknown>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Silently build an invocation (used by upstream tool execution flow).
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Build an invocation object from params — used by Scheduler.
|
|
39
|
+
*/
|
|
40
|
+
build(params: Record<string, unknown>): {
|
|
41
|
+
name: string;
|
|
42
|
+
execute: (abortSignal: AbortSignal) => Promise<{
|
|
43
|
+
llmContent: string;
|
|
44
|
+
returnDisplay?: string;
|
|
45
|
+
error?: {
|
|
46
|
+
message: string;
|
|
47
|
+
type: string;
|
|
48
|
+
};
|
|
49
|
+
}>;
|
|
50
|
+
};
|
|
51
|
+
silentBuild(params: Record<string, unknown>): {
|
|
52
|
+
name: string;
|
|
53
|
+
execute: (abortSignal: AbortSignal) => Promise<{
|
|
54
|
+
llmContent: string;
|
|
55
|
+
returnDisplay?: string;
|
|
56
|
+
error?: {
|
|
57
|
+
message: string;
|
|
58
|
+
type: string;
|
|
59
|
+
};
|
|
60
|
+
}>;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Build and execute in one step — matches the upstream DeclarativeTool interface.
|
|
64
|
+
*/
|
|
65
|
+
validateBuildAndExecute(params: Record<string, unknown>, abortSignal: AbortSignal): Promise<{
|
|
66
|
+
llmContent: string;
|
|
67
|
+
returnDisplay?: string;
|
|
68
|
+
error?: {
|
|
69
|
+
message: string;
|
|
70
|
+
type: string;
|
|
71
|
+
};
|
|
72
|
+
}>;
|
|
73
|
+
private buildContext;
|
|
74
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Adapts a repo LoadedTool to the upstream tool registry interface.
|
|
8
|
+
* Wraps the tool definition and delegates execution to the CustomToolExecutor.
|
|
9
|
+
*/
|
|
10
|
+
export class CustomToolAdapter {
|
|
11
|
+
name;
|
|
12
|
+
displayName;
|
|
13
|
+
tool;
|
|
14
|
+
session;
|
|
15
|
+
executor;
|
|
16
|
+
kind = 'declarative';
|
|
17
|
+
description;
|
|
18
|
+
parameterSchema;
|
|
19
|
+
constructor(tool, session, executor) {
|
|
20
|
+
this.name = tool.name;
|
|
21
|
+
this.displayName = tool.name;
|
|
22
|
+
this.description = tool.description;
|
|
23
|
+
this.parameterSchema = tool.parameters;
|
|
24
|
+
this.tool = tool;
|
|
25
|
+
this.session = session;
|
|
26
|
+
this.executor = executor;
|
|
27
|
+
}
|
|
28
|
+
get isReadOnly() {
|
|
29
|
+
return this.tool.confirm === false;
|
|
30
|
+
}
|
|
31
|
+
get toolAnnotations() {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
getSchema(_modelId) {
|
|
35
|
+
return {
|
|
36
|
+
name: this.name,
|
|
37
|
+
description: this.description,
|
|
38
|
+
parametersJsonSchema: this.parameterSchema,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
get schema() {
|
|
42
|
+
return this.getSchema();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Silently build an invocation (used by upstream tool execution flow).
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Build an invocation object from params — used by Scheduler.
|
|
49
|
+
*/
|
|
50
|
+
build(params) {
|
|
51
|
+
return {
|
|
52
|
+
name: this.name,
|
|
53
|
+
execute: async (abortSignal) => this.validateBuildAndExecute(params, abortSignal),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
silentBuild(params) {
|
|
57
|
+
return this.build(params);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build and execute in one step — matches the upstream DeclarativeTool interface.
|
|
61
|
+
*/
|
|
62
|
+
async validateBuildAndExecute(params, abortSignal) {
|
|
63
|
+
try {
|
|
64
|
+
const ctx = this.buildContext(abortSignal);
|
|
65
|
+
const result = await this.executor.execute(this.tool, params, ctx);
|
|
66
|
+
const content = typeof result === 'string' ? result : JSON.stringify(result);
|
|
67
|
+
return { llmContent: content, returnDisplay: content };
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
71
|
+
return {
|
|
72
|
+
llmContent: `Error: ${message}`,
|
|
73
|
+
returnDisplay: message,
|
|
74
|
+
error: { message, type: 'EXECUTION_FAILED' },
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
buildContext(signal) {
|
|
79
|
+
const tool = this.tool;
|
|
80
|
+
const session = this.session;
|
|
81
|
+
const timeoutSignal = AbortSignal.timeout(tool.timeout);
|
|
82
|
+
const combinedSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
83
|
+
return {
|
|
84
|
+
async request(connection, endpoint, params) {
|
|
85
|
+
const connections = session.config.getConnections();
|
|
86
|
+
const connConfig = connections[connection];
|
|
87
|
+
if (!connConfig) {
|
|
88
|
+
throw new Error(`Connection "${connection}" not found`);
|
|
89
|
+
}
|
|
90
|
+
const method = params?.method ?? 'GET';
|
|
91
|
+
if (tool.confirm === false && method !== 'GET') {
|
|
92
|
+
throw new Error(`Tool "${tool.name}" has confirm: false — only GET requests are allowed.`);
|
|
93
|
+
}
|
|
94
|
+
const baseUrl = typeof connConfig === 'object' && connConfig !== null && 'baseUrl' in connConfig
|
|
95
|
+
? String(connConfig['baseUrl'] ?? '')
|
|
96
|
+
: '';
|
|
97
|
+
if (!baseUrl) {
|
|
98
|
+
throw new Error(`Connection "${connection}" has no baseUrl`);
|
|
99
|
+
}
|
|
100
|
+
const url = `${baseUrl}${endpoint}`;
|
|
101
|
+
const fetchOpts = {
|
|
102
|
+
method,
|
|
103
|
+
signal: combinedSignal,
|
|
104
|
+
headers: { 'Content-Type': 'application/json' },
|
|
105
|
+
};
|
|
106
|
+
if (params?.data) {
|
|
107
|
+
fetchOpts.body = JSON.stringify(params.data);
|
|
108
|
+
}
|
|
109
|
+
const res = await fetch(url, fetchOpts);
|
|
110
|
+
const body = await res.text();
|
|
111
|
+
try {
|
|
112
|
+
return JSON.parse(body);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return { text: body, status: res.status };
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
async exec(command, options) {
|
|
119
|
+
const { exec: execCb } = await import('node:child_process');
|
|
120
|
+
const { promisify } = await import('node:util');
|
|
121
|
+
const execAsync = promisify(execCb);
|
|
122
|
+
try {
|
|
123
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
124
|
+
signal: combinedSignal,
|
|
125
|
+
timeout: options?.timeout ?? tool.timeout,
|
|
126
|
+
cwd: options?.cwd,
|
|
127
|
+
});
|
|
128
|
+
return { stdout: stdout ?? '', stderr: stderr ?? '', exitCode: 0 };
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- exec error shape
|
|
132
|
+
const e = err;
|
|
133
|
+
return { stdout: e.stdout ?? '', stderr: e.stderr ?? '', exitCode: e.code ?? 1 };
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
env(name) {
|
|
137
|
+
if (!tool.env.includes(name))
|
|
138
|
+
return undefined;
|
|
139
|
+
return process.env[name];
|
|
140
|
+
},
|
|
141
|
+
log(message) {
|
|
142
|
+
process.stderr.write(`[TOOL:${tool.name}] ${message}\n`);
|
|
143
|
+
},
|
|
144
|
+
user: { roles: [] },
|
|
145
|
+
signal: combinedSignal,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=custom-tool-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-tool-adapter.js","sourceRoot":"","sources":["../../../src/session/custom-tool-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACnB,IAAI,CAAS;IACb,WAAW,CAAS;IACZ,IAAI,CAAa;IACjB,OAAO,CAAiB;IACxB,QAAQ,CAAqB;IACrC,IAAI,GAAG,aAAsB,CAAC;IAE9B,WAAW,CAAS;IACpB,eAAe,CAA0B;IAElD,YAAY,IAAgB,EAAE,OAAuB,EAAE,QAA4B;QACjF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC;IACrC,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,SAAS,CAAC,QAAiB;QACzB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,oBAAoB,EAAE,IAAI,CAAC,eAAe;SAC3C,CAAC;IACJ,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH;;OAEG;IACH,KAAK,CAAC,MAA+B;QACnC,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,KAAK,EAAE,WAAwB,EAAE,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,WAAW,CAAC;SAC/F,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,MAA+B;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB,CAC3B,MAA+B,EAC/B,WAAwB;QAExB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YACnE,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC7E,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO;gBACL,UAAU,EAAE,UAAU,OAAO,EAAE;gBAC/B,aAAa,EAAE,OAAO;gBACtB,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE;aAC7C,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,MAAmB;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;QAEhE,OAAO;YACL,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM;gBACxC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;gBACpD,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;gBAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,aAAa,CAAC,CAAC;gBAC1D,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,KAAK,CAAC;gBACvC,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;oBAC/C,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,IAAI,uDAAuD,CAC1E,CAAC;gBACJ,CAAC;gBAED,MAAM,OAAO,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,IAAI,SAAS,IAAI,UAAU;oBAC9F,CAAC,CAAC,MAAM,CAAE,UAAsC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;oBAClE,CAAC,CAAC,EAAE,CAAC;gBAEP,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,kBAAkB,CAAC,CAAC;gBAC/D,CAAC;gBAED,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,EAAE,CAAC;gBACpC,MAAM,SAAS,GAAgB;oBAC7B,MAAM;oBACN,MAAM,EAAE,cAAc;oBACtB,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC;gBACF,IAAI,MAAM,EAAE,IAAI,EAAE,CAAC;oBACjB,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC/C,CAAC;gBAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBACxC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC9B,IAAI,CAAC;oBAEH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC5C,CAAC;YACH,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO;gBACzB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;gBAC5D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;gBAChD,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;gBACpC,IAAI,CAAC;oBACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE;wBAClD,MAAM,EAAE,cAAc;wBACtB,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO;wBACzC,GAAG,EAAE,OAAO,EAAE,GAAG;qBAClB,CAAC,CAAC;oBACH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;gBACrE,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,2FAA2F;oBAC3F,MAAM,CAAC,GAAG,GAA0D,CAAC;oBACrE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;gBACnF,CAAC;YACH,CAAC;YAED,GAAG,CAAC,IAAY;gBACd,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,OAAO,SAAS,CAAC;gBAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;YAED,GAAG,CAAC,OAAe;gBACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YAEnB,MAAM,EAAE,cAAc;SACvB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Copyright 2025 Amodal Labs, Inc.
|
|
4
4
|
* SPDX-License-Identifier: MIT
|
|
5
5
|
*/
|
|
6
|
-
import { AmodalConfig, type AmodalConfigParameters, Scheduler, type GeminiClient } from '@amodalai/core';
|
|
6
|
+
import { AmodalConfig, type AmodalConfigParameters, Scheduler, type GeminiClient, PlanModeManager, McpManager } from '@amodalai/core';
|
|
7
|
+
import type { AmodalRepo, CustomToolExecutor, CustomShellExecutor, StoreBackend } from '@amodalai/core';
|
|
7
8
|
import type { AuthContext } from '../middleware/auth.js';
|
|
8
9
|
export interface PendingAskUser {
|
|
9
10
|
resolve: (answers: Record<string, string>) => void;
|
|
@@ -39,7 +40,36 @@ export interface ManagedSession {
|
|
|
39
40
|
/** Provider used for this session (pinned at creation, survives hydration) */
|
|
40
41
|
provider?: string;
|
|
41
42
|
/** Store backend for cleanup on session destroy */
|
|
42
|
-
storeBackend?:
|
|
43
|
+
storeBackend?: StoreBackend;
|
|
44
|
+
/** Plan mode manager (local dev) */
|
|
45
|
+
planModeManager?: PlanModeManager;
|
|
46
|
+
/** MCP server manager (local dev) */
|
|
47
|
+
mcpManager?: McpManager;
|
|
48
|
+
/** Session title */
|
|
49
|
+
title?: string;
|
|
50
|
+
/** Custom tool executor (local dev) */
|
|
51
|
+
toolExecutor?: CustomToolExecutor;
|
|
52
|
+
/** Custom shell executor (local dev) */
|
|
53
|
+
shellExecutor?: CustomShellExecutor;
|
|
54
|
+
/** App ID for this session */
|
|
55
|
+
appId?: string;
|
|
56
|
+
}
|
|
57
|
+
/** Shape of a stored session record (from platform API or session store). */
|
|
58
|
+
export interface StoredSessionRecord {
|
|
59
|
+
id: string;
|
|
60
|
+
app_id: string;
|
|
61
|
+
messages: SessionMessage[];
|
|
62
|
+
status: string;
|
|
63
|
+
model?: string;
|
|
64
|
+
provider?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Pluggable session store for loading stored session history.
|
|
68
|
+
* Implementations are provided by the hosting layer.
|
|
69
|
+
*/
|
|
70
|
+
export interface SessionStore {
|
|
71
|
+
/** Fetch a stored session record by ID. Returns null if not found. */
|
|
72
|
+
getSession(appId: string, sessionId: string, token: string): Promise<StoredSessionRecord | null>;
|
|
43
73
|
}
|
|
44
74
|
export interface SessionManagerOptions {
|
|
45
75
|
/** Base config parameters to clone for each session */
|
|
@@ -50,15 +80,39 @@ export interface SessionManagerOptions {
|
|
|
50
80
|
cleanupIntervalMs?: number;
|
|
51
81
|
/** Platform API URL (for loading org-specific config per session) */
|
|
52
82
|
platformApiUrl?: string;
|
|
83
|
+
/** Repo for local dev mode — sessions initialized from repo config instead of platform API */
|
|
84
|
+
repo?: AmodalRepo;
|
|
85
|
+
/** Custom tool executor (local dev) */
|
|
86
|
+
toolExecutor?: CustomToolExecutor;
|
|
87
|
+
/** Custom shell executor (local dev) */
|
|
88
|
+
shellExecutor?: CustomShellExecutor;
|
|
89
|
+
/** Shared store backend (local dev) */
|
|
90
|
+
storeBackend?: StoreBackend;
|
|
91
|
+
/** Pluggable session store for hydration (if not provided, falls back to platform API) */
|
|
92
|
+
sessionStore?: SessionStore;
|
|
53
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Manages per-request sessions: creates Config + GeminiClient + Scheduler
|
|
96
|
+
* instances, tracks them by ID, and cleans up expired sessions.
|
|
97
|
+
*/
|
|
54
98
|
export declare class SessionManager {
|
|
55
99
|
private readonly sessions;
|
|
56
|
-
private
|
|
100
|
+
private baseParams;
|
|
57
101
|
private readonly ttlMs;
|
|
58
102
|
private readonly platformApiUrl?;
|
|
103
|
+
private repo?;
|
|
104
|
+
private readonly toolExecutor?;
|
|
105
|
+
private readonly shellExecutor?;
|
|
106
|
+
private readonly sharedStoreBackend?;
|
|
107
|
+
private readonly sessionStore?;
|
|
59
108
|
private cleanupTimer;
|
|
60
109
|
/** Deduplicates concurrent hydration requests for the same conversation */
|
|
61
110
|
private readonly pendingHydrations;
|
|
111
|
+
/** Shared MCP manager for all sessions (lazy-initialized, reused) */
|
|
112
|
+
private sharedMcpManager?;
|
|
113
|
+
/** Persistent MCP manager for inspect operations (lazy-initialized) */
|
|
114
|
+
private inspectMcp?;
|
|
115
|
+
private inspectMcpInitialized;
|
|
62
116
|
constructor(options: SessionManagerOptions);
|
|
63
117
|
/**
|
|
64
118
|
* Create a new session with optional role override and auth context.
|
|
@@ -91,6 +145,50 @@ export declare class SessionManager {
|
|
|
91
145
|
* Destroy a session, flushing its audit log.
|
|
92
146
|
*/
|
|
93
147
|
destroy(id: string): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Get the repo (local dev mode).
|
|
150
|
+
*/
|
|
151
|
+
getRepo(): AmodalRepo | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Update the repo for new sessions (hot reload).
|
|
154
|
+
* Existing sessions keep their old config.
|
|
155
|
+
*/
|
|
156
|
+
updateRepo(repo: AmodalRepo): void;
|
|
157
|
+
/**
|
|
158
|
+
* Re-register a session under a different ID (e.g., restoring original ID on session restore).
|
|
159
|
+
*/
|
|
160
|
+
reregister(session: ManagedSession, newId: string): void;
|
|
161
|
+
/**
|
|
162
|
+
* Create an admin session for the config chat.
|
|
163
|
+
* Uses admin agent skills/knowledge but the current repo's connections/stores.
|
|
164
|
+
*
|
|
165
|
+
* Temporarily swaps repo fields so create() builds the prompt with admin
|
|
166
|
+
* content, then restores the original repo. This mirrors the old approach
|
|
167
|
+
* of building an adminRepo overlay.
|
|
168
|
+
*/
|
|
169
|
+
createAdminSession(getPort?: () => number | null): Promise<ManagedSession>;
|
|
170
|
+
/**
|
|
171
|
+
* Get a persistent MCP manager for inspect/health operations.
|
|
172
|
+
* Lazy-initialized on first call, reused across requests.
|
|
173
|
+
*/
|
|
174
|
+
getInspectMcpManager(): Promise<McpManager | undefined>;
|
|
175
|
+
/**
|
|
176
|
+
* Initialize MCP servers for a session from repo connections.
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Initialize the shared MCP manager (once, reused across sessions).
|
|
180
|
+
* Avoids reconnecting MCP servers for every eval/judge/admin session.
|
|
181
|
+
*/
|
|
182
|
+
private initSharedMcp;
|
|
183
|
+
/**
|
|
184
|
+
* Build the list of upstream core tools to enable based on repo config.
|
|
185
|
+
* Only tools relevant to the Amodal runtime are included.
|
|
186
|
+
*/
|
|
187
|
+
private buildCoreToolsList;
|
|
188
|
+
/**
|
|
189
|
+
* Build MCP server configs from repo connections.
|
|
190
|
+
*/
|
|
191
|
+
private buildMcpConfigs;
|
|
94
192
|
/**
|
|
95
193
|
* Remove sessions that have been idle longer than the TTL.
|
|
96
194
|
*/
|