@redplanethq/corebrain 2.8.12 → 2.8.14
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/commands/coding/list.js +1 -1
- package/dist/commands/coding/list.js.map +1 -1
- package/dist/commands/coding/setup.d.ts +2 -1
- package/dist/commands/coding/setup.d.ts.map +1 -1
- package/dist/commands/coding/setup.js +1 -24
- package/dist/commands/coding/setup.js.map +1 -1
- package/dist/commands/folder/add.d.ts +13 -0
- package/dist/commands/folder/add.d.ts.map +1 -0
- package/dist/commands/folder/add.js +71 -0
- package/dist/commands/folder/add.js.map +1 -0
- package/dist/commands/folder/index.d.ts +3 -0
- package/dist/commands/folder/index.d.ts.map +1 -0
- package/dist/commands/folder/index.js +5 -0
- package/dist/commands/folder/index.js.map +1 -0
- package/dist/commands/folder/list.d.ts +8 -0
- package/dist/commands/folder/list.d.ts.map +1 -0
- package/dist/commands/folder/list.js +39 -0
- package/dist/commands/folder/list.js.map +1 -0
- package/dist/commands/folder/remove.d.ts +10 -0
- package/dist/commands/folder/remove.d.ts.map +1 -0
- package/dist/commands/folder/remove.js +29 -0
- package/dist/commands/folder/remove.js.map +1 -0
- package/dist/commands/folder/scope.d.ts +13 -0
- package/dist/commands/folder/scope.d.ts.map +1 -0
- package/dist/commands/folder/scope.js +61 -0
- package/dist/commands/folder/scope.js.map +1 -0
- package/dist/commands/gateway/config.d.ts +1 -1
- package/dist/commands/gateway/config.d.ts.map +1 -1
- package/dist/commands/gateway/config.js +122 -116
- package/dist/commands/gateway/config.js.map +1 -1
- package/dist/commands/gateway/register.d.ts +37 -0
- package/dist/commands/gateway/register.d.ts.map +1 -0
- package/dist/commands/gateway/register.js +132 -0
- package/dist/commands/gateway/register.js.map +1 -0
- package/dist/commands/gateway/start.d.ts +2 -1
- package/dist/commands/gateway/start.d.ts.map +1 -1
- package/dist/commands/gateway/start.js +73 -6
- package/dist/commands/gateway/start.js.map +1 -1
- package/dist/commands/gateway/status.d.ts.map +1 -1
- package/dist/commands/gateway/status.js +10 -1
- package/dist/commands/gateway/status.js.map +1 -1
- package/dist/commands/gateway/stop.d.ts.map +1 -1
- package/dist/commands/gateway/stop.js +11 -0
- package/dist/commands/gateway/stop.js.map +1 -1
- package/dist/config/folders.d.ts +20 -0
- package/dist/config/folders.d.ts.map +1 -0
- package/dist/config/folders.js +114 -0
- package/dist/config/folders.js.map +1 -0
- package/dist/server/api/auth.d.ts +17 -0
- package/dist/server/api/auth.d.ts.map +1 -0
- package/dist/server/api/auth.js +45 -0
- package/dist/server/api/auth.js.map +1 -0
- package/dist/server/api/browser/cdp.d.ts +18 -0
- package/dist/server/api/browser/cdp.d.ts.map +1 -0
- package/dist/server/api/browser/cdp.js +137 -0
- package/dist/server/api/browser/cdp.js.map +1 -0
- package/dist/server/api/browser/index.d.ts +3 -0
- package/dist/server/api/browser/index.d.ts.map +1 -0
- package/dist/server/api/browser/index.js +10 -0
- package/dist/server/api/browser/index.js.map +1 -0
- package/dist/server/api/browser/launch.d.ts +17 -0
- package/dist/server/api/browser/launch.d.ts.map +1 -0
- package/dist/server/api/browser/launch.js +41 -0
- package/dist/server/api/browser/launch.js.map +1 -0
- package/dist/server/api/coding/coding_spawn.d.ts +22 -0
- package/dist/server/api/coding/coding_spawn.d.ts.map +1 -0
- package/dist/server/api/coding/coding_spawn.js +121 -0
- package/dist/server/api/coding/coding_spawn.js.map +1 -0
- package/dist/server/api/coding/coding_xterm_session.d.ts +3 -0
- package/dist/server/api/coding/coding_xterm_session.d.ts.map +1 -0
- package/dist/server/api/coding/coding_xterm_session.js +163 -0
- package/dist/server/api/coding/coding_xterm_session.js.map +1 -0
- package/dist/server/api/coding/index.d.ts +10 -0
- package/dist/server/api/coding/index.d.ts.map +1 -0
- package/dist/server/api/coding/index.js +17 -0
- package/dist/server/api/coding/index.js.map +1 -0
- package/dist/server/api/exec/index.d.ts +3 -0
- package/dist/server/api/exec/index.d.ts.map +1 -0
- package/dist/server/api/exec/index.js +6 -0
- package/dist/server/api/exec/index.js.map +1 -0
- package/dist/server/api/files/index.d.ts +3 -0
- package/dist/server/api/files/index.d.ts.map +1 -0
- package/dist/server/api/files/index.js +6 -0
- package/dist/server/api/files/index.js.map +1 -0
- package/dist/server/api/folders/index.d.ts +14 -0
- package/dist/server/api/folders/index.d.ts.map +1 -0
- package/dist/server/api/folders/index.js +161 -0
- package/dist/server/api/folders/index.js.map +1 -0
- package/dist/server/api/manifest-builder.d.ts +13 -0
- package/dist/server/api/manifest-builder.d.ts.map +1 -0
- package/dist/server/api/manifest-builder.js +155 -0
- package/dist/server/api/manifest-builder.js.map +1 -0
- package/dist/server/api/ops.d.ts +3 -0
- package/dist/server/api/ops.d.ts.map +1 -0
- package/dist/server/api/ops.js +32 -0
- package/dist/server/api/ops.js.map +1 -0
- package/dist/server/api/server.d.ts +9 -0
- package/dist/server/api/server.d.ts.map +1 -0
- package/dist/server/api/server.js +66 -0
- package/dist/server/api/server.js.map +1 -0
- package/dist/server/api/shell/index.d.ts +17 -0
- package/dist/server/api/shell/index.d.ts.map +1 -0
- package/dist/server/api/shell/index.js +61 -0
- package/dist/server/api/shell/index.js.map +1 -0
- package/dist/server/api/tool-group.d.ts +21 -0
- package/dist/server/api/tool-group.d.ts.map +1 -0
- package/dist/server/api/tool-group.js +23 -0
- package/dist/server/api/tool-group.js.map +1 -0
- package/dist/server/api/tunnels/ngrok.d.ts +10 -0
- package/dist/server/api/tunnels/ngrok.d.ts.map +1 -0
- package/dist/server/api/tunnels/ngrok.js +33 -0
- package/dist/server/api/tunnels/ngrok.js.map +1 -0
- package/dist/server/api/tunnels/tailscale.d.ts +12 -0
- package/dist/server/api/tunnels/tailscale.d.ts.map +1 -0
- package/dist/server/api/tunnels/tailscale.js +49 -0
- package/dist/server/api/tunnels/tailscale.js.map +1 -0
- package/dist/server/api/utils/index.d.ts +3 -0
- package/dist/server/api/utils/index.d.ts.map +1 -0
- package/dist/server/api/utils/index.js +6 -0
- package/dist/server/api/utils/index.js.map +1 -0
- package/dist/server/gateway-entry.d.ts +2 -2
- package/dist/server/gateway-entry.js +43 -106
- package/dist/server/gateway-entry.js.map +1 -1
- package/dist/server/gateway-log.d.ts +10 -0
- package/dist/server/gateway-log.d.ts.map +1 -0
- package/dist/server/gateway-log.js +33 -0
- package/dist/server/gateway-log.js.map +1 -0
- package/dist/server/pty/manager.d.ts +75 -0
- package/dist/server/pty/manager.d.ts.map +1 -0
- package/dist/server/pty/manager.js +280 -0
- package/dist/server/pty/manager.js.map +1 -0
- package/dist/server/tools/coding-tools.d.ts.map +1 -1
- package/dist/server/tools/coding-tools.js +83 -19
- package/dist/server/tools/coding-tools.js.map +1 -1
- package/dist/server/tools/exec-tools.d.ts.map +1 -1
- package/dist/server/tools/exec-tools.js +30 -3
- package/dist/server/tools/exec-tools.js.map +1 -1
- package/dist/server/tools/files-tools.d.ts +8 -0
- package/dist/server/tools/files-tools.d.ts.map +1 -0
- package/dist/server/tools/files-tools.js +523 -0
- package/dist/server/tools/files-tools.js.map +1 -0
- package/dist/server/tools/scope-error.d.ts +8 -0
- package/dist/server/tools/scope-error.d.ts.map +1 -0
- package/dist/server/tools/scope-error.js +11 -0
- package/dist/server/tools/scope-error.js.map +1 -0
- package/dist/types/config.d.ts +15 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/agent-templates.d.ts +18 -0
- package/dist/utils/agent-templates.d.ts.map +1 -0
- package/dist/utils/agent-templates.js +59 -0
- package/dist/utils/agent-templates.js.map +1 -0
- package/dist/utils/browser-manager.d.ts +20 -0
- package/dist/utils/browser-manager.d.ts.map +1 -1
- package/dist/utils/browser-manager.js +76 -0
- package/dist/utils/browser-manager.js.map +1 -1
- package/dist/utils/coding-agents/claude-code.d.ts +1 -0
- package/dist/utils/coding-agents/claude-code.d.ts.map +1 -1
- package/dist/utils/coding-agents/claude-code.js +9 -0
- package/dist/utils/coding-agents/claude-code.js.map +1 -1
- package/dist/utils/coding-agents/codex.d.ts +6 -8
- package/dist/utils/coding-agents/codex.d.ts.map +1 -1
- package/dist/utils/coding-agents/codex.js +16 -19
- package/dist/utils/coding-agents/codex.js.map +1 -1
- package/dist/utils/coding-agents/index.d.ts +1 -0
- package/dist/utils/coding-agents/index.d.ts.map +1 -1
- package/dist/utils/coding-agents/index.js +3 -0
- package/dist/utils/coding-agents/index.js.map +1 -1
- package/dist/utils/coding-agents/types.d.ts +6 -0
- package/dist/utils/coding-agents/types.d.ts.map +1 -1
- package/dist/utils/coding-agents/types.js.map +1 -1
- package/dist/utils/coding-runner.d.ts +13 -9
- package/dist/utils/coding-runner.d.ts.map +1 -1
- package/dist/utils/coding-runner.js +45 -78
- package/dist/utils/coding-runner.js.map +1 -1
- package/dist/utils/env-bootstrap.d.ts +29 -0
- package/dist/utils/env-bootstrap.d.ts.map +1 -0
- package/dist/utils/env-bootstrap.js +204 -0
- package/dist/utils/env-bootstrap.js.map +1 -0
- package/package.json +8 -1
- package/dist/commands/coding/close.d.ts +0 -11
- package/dist/commands/coding/close.d.ts.map +0 -1
- package/dist/commands/coding/close.js +0 -76
- package/dist/commands/coding/close.js.map +0 -1
- package/dist/commands/coding/resume.d.ts +0 -12
- package/dist/commands/coding/resume.d.ts.map +0 -1
- package/dist/commands/coding/resume.js +0 -86
- package/dist/commands/coding/resume.js.map +0 -1
- package/dist/commands/coding/start.d.ts +0 -17
- package/dist/commands/coding/start.d.ts.map +0 -1
- package/dist/commands/coding/start.js +0 -135
- package/dist/commands/coding/start.js.map +0 -1
- package/dist/server/gateway-client.d.ts +0 -84
- package/dist/server/gateway-client.d.ts.map +0 -1
- package/dist/server/gateway-client.js +0 -340
- package/dist/server/gateway-client.js.map +0 -1
- package/dist/server/tools/imessage-tools.d.ts +0 -34
- package/dist/server/tools/imessage-tools.d.ts.map +0 -1
- package/dist/server/tools/imessage-tools.js +0 -262
- package/dist/server/tools/imessage-tools.js.map +0 -1
- package/dist/utils/app-bundle.d.ts +0 -25
- package/dist/utils/app-bundle.d.ts.map +0 -1
- package/dist/utils/app-bundle.js +0 -117
- package/dist/utils/app-bundle.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/api/files/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAIhD,eAAO,MAAM,WAAW,EAAE,kBAEzB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { filesTools, executeFilesTool } from '../../../server/tools/files-tools.js';
|
|
2
|
+
import { makeToolGroupRoutes } from '../tool-group.js';
|
|
3
|
+
export const filesRoutes = async (app) => {
|
|
4
|
+
await app.register(makeToolGroupRoutes(filesTools, executeFilesTool));
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/api/files/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAE,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAC,mBAAmB,EAAC,MAAM,eAAe,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAuB,KAAK,EAAE,GAAG,EAAE,EAAE;IAC5D,MAAM,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from 'fastify';
|
|
2
|
+
/**
|
|
3
|
+
* Folder management routes (mounted at `/api/folders`).
|
|
4
|
+
*
|
|
5
|
+
* GET /api/folders → manifest mirror, used by webapp settings
|
|
6
|
+
* POST /api/folders/local → register an existing on-disk path
|
|
7
|
+
* POST /api/folders/git → git clone <url> into the workspace, register
|
|
8
|
+
* DELETE /api/folders/:idOrName → unregister (does not delete files)
|
|
9
|
+
*
|
|
10
|
+
* Auth is handled upstream (`makeAuthHook`); these handlers assume the caller
|
|
11
|
+
* already passed the gateway's security key.
|
|
12
|
+
*/
|
|
13
|
+
export declare const folderRoutes: FastifyPluginAsync;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/api/folders/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAUhD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,kBAyK1B,CAAC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { existsSync, mkdirSync, statSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { addFolder, listFolders, removeFolder } from '../../../config/folders.js';
|
|
6
|
+
import { gatewayLog } from '../../../server/gateway-log.js';
|
|
7
|
+
const execFileP = promisify(execFile);
|
|
8
|
+
/**
|
|
9
|
+
* Folder management routes (mounted at `/api/folders`).
|
|
10
|
+
*
|
|
11
|
+
* GET /api/folders → manifest mirror, used by webapp settings
|
|
12
|
+
* POST /api/folders/local → register an existing on-disk path
|
|
13
|
+
* POST /api/folders/git → git clone <url> into the workspace, register
|
|
14
|
+
* DELETE /api/folders/:idOrName → unregister (does not delete files)
|
|
15
|
+
*
|
|
16
|
+
* Auth is handled upstream (`makeAuthHook`); these handlers assume the caller
|
|
17
|
+
* already passed the gateway's security key.
|
|
18
|
+
*/
|
|
19
|
+
export const folderRoutes = async (app) => {
|
|
20
|
+
// ---- list ----
|
|
21
|
+
app.get('/', async () => ({
|
|
22
|
+
ok: true,
|
|
23
|
+
folders: listFolders(),
|
|
24
|
+
}));
|
|
25
|
+
// ---- register existing local path ----
|
|
26
|
+
app.post('/local', async (req, reply) => {
|
|
27
|
+
const body = (req.body ?? {});
|
|
28
|
+
if (!body.path) {
|
|
29
|
+
reply.code(400);
|
|
30
|
+
return { ok: false, error: '`path` is required' };
|
|
31
|
+
}
|
|
32
|
+
const scopes = body.scopes && body.scopes.length > 0
|
|
33
|
+
? body.scopes
|
|
34
|
+
: ['files', 'coding', 'exec'];
|
|
35
|
+
try {
|
|
36
|
+
const folder = addFolder({
|
|
37
|
+
name: body.name,
|
|
38
|
+
path: body.path,
|
|
39
|
+
scopes: scopes,
|
|
40
|
+
});
|
|
41
|
+
gatewayLog(`folder added (local): ${folder.name} → ${folder.path}`);
|
|
42
|
+
return { ok: true, folder };
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
reply.code(400);
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
error: err instanceof Error ? err.message : 'failed to add folder',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
// ---- clone github / git url, register the clone ----
|
|
53
|
+
app.post('/git', async (req, reply) => {
|
|
54
|
+
const body = (req.body ?? {});
|
|
55
|
+
if (!body.url) {
|
|
56
|
+
reply.code(400);
|
|
57
|
+
return { ok: false, error: '`url` is required' };
|
|
58
|
+
}
|
|
59
|
+
const workspaceRoot = process.env.COREBRAIN_DEFAULT_WORKSPACE || '/app';
|
|
60
|
+
if (!existsSync(workspaceRoot)) {
|
|
61
|
+
try {
|
|
62
|
+
mkdirSync(workspaceRoot, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
reply.code(500);
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
error: `workspace dir ${workspaceRoot} missing and could not be created`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
if (!statSync(workspaceRoot).isDirectory()) {
|
|
74
|
+
reply.code(500);
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
error: `workspace path ${workspaceRoot} is not a directory`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
reply.code(500);
|
|
83
|
+
return { ok: false, error: `workspace path ${workspaceRoot} not accessible` };
|
|
84
|
+
}
|
|
85
|
+
// Default folder name: derive from the repo URL (".../foo/bar.git" → "bar").
|
|
86
|
+
const defaultName = body.name ??
|
|
87
|
+
body.url
|
|
88
|
+
.replace(/\/$/, '')
|
|
89
|
+
.replace(/\.git$/i, '')
|
|
90
|
+
.split('/')
|
|
91
|
+
.pop() ??
|
|
92
|
+
'repo';
|
|
93
|
+
// Sanitize so we don't end up with something silly like "../etc" inside
|
|
94
|
+
// /app. Letters, digits, dot, dash, underscore only — anything else
|
|
95
|
+
// becomes "-".
|
|
96
|
+
const safeName = defaultName.replace(/[^a-zA-Z0-9._-]/g, '-');
|
|
97
|
+
const target = join(workspaceRoot, safeName);
|
|
98
|
+
if (existsSync(target)) {
|
|
99
|
+
reply.code(409);
|
|
100
|
+
return { ok: false, error: `target dir already exists: ${target}` };
|
|
101
|
+
}
|
|
102
|
+
const args = ['clone', '--depth', '1'];
|
|
103
|
+
if (body.branch) {
|
|
104
|
+
args.push('--branch', body.branch, '--single-branch');
|
|
105
|
+
}
|
|
106
|
+
args.push(body.url, target);
|
|
107
|
+
gatewayLog(`folder add (git): cloning ${body.url} → ${target}`);
|
|
108
|
+
try {
|
|
109
|
+
await execFileP('git', args, {
|
|
110
|
+
timeout: 5 * 60_000, // 5 minutes
|
|
111
|
+
env: process.env,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
reply.code(502);
|
|
116
|
+
const stderr = err?.stderr;
|
|
117
|
+
const message = stderr
|
|
118
|
+
? Buffer.isBuffer(stderr)
|
|
119
|
+
? stderr.toString('utf8')
|
|
120
|
+
: stderr
|
|
121
|
+
: err instanceof Error
|
|
122
|
+
? err.message
|
|
123
|
+
: 'git clone failed';
|
|
124
|
+
gatewayLog(`folder add (git) FAILED: ${message.trim()}`);
|
|
125
|
+
return { ok: false, error: message.trim() };
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const folder = addFolder({
|
|
129
|
+
name: safeName,
|
|
130
|
+
path: target,
|
|
131
|
+
scopes: ['files', 'coding', 'exec'],
|
|
132
|
+
});
|
|
133
|
+
gatewayLog(`folder added (git): ${folder.name} → ${folder.path}`);
|
|
134
|
+
return { ok: true, folder };
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
reply.code(500);
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
error: err instanceof Error ? err.message : 'failed to register clone',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
// ---- unregister (does not delete files on disk) ----
|
|
145
|
+
app.delete('/:idOrName', async (req, reply) => {
|
|
146
|
+
const { idOrName } = req.params;
|
|
147
|
+
try {
|
|
148
|
+
removeFolder(idOrName);
|
|
149
|
+
gatewayLog(`folder removed: ${idOrName}`);
|
|
150
|
+
return { ok: true };
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
reply.code(404);
|
|
154
|
+
return {
|
|
155
|
+
ok: false,
|
|
156
|
+
error: err instanceof Error ? err.message : 'not found',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/api/folders/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Manifest } from '@core/gateway-protocol';
|
|
2
|
+
import type { GatewaySlots } from '../../types/config.js';
|
|
3
|
+
/**
|
|
4
|
+
* A slot is considered enabled unless the user explicitly disabled it via
|
|
5
|
+
* `corebrain gateway config` (slots[name].enabled === false). Missing config
|
|
6
|
+
* means enabled, for backwards compatibility.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isSlotEnabled(slots: GatewaySlots | undefined, slot: keyof GatewaySlots): boolean;
|
|
9
|
+
export declare function buildManifest(): {
|
|
10
|
+
manifest: Manifest;
|
|
11
|
+
etag: string;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=manifest-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-builder.d.ts","sourceRoot":"","sources":["../../../src/server/api/manifest-builder.ts"],"names":[],"mappings":"AAIA,OAAO,EAEN,KAAK,QAAQ,EAGb,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAgB,YAAY,EAAC,MAAM,gBAAgB,CAAC;AA8FhE;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,YAAY,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,YAAY,GACtB,OAAO,CAKT;AAED,wBAAgB,aAAa,IAAI;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAsDlE"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { hostname, platform } from 'node:os';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { PROTOCOL_VERSION, } from '@core/gateway-protocol';
|
|
6
|
+
import { getPreferences } from '../../config/preferences.js';
|
|
7
|
+
import { listFolders } from '../../config/folders.js';
|
|
8
|
+
import { browserTools } from '../../server/tools/browser-tools.js';
|
|
9
|
+
import { codingTools } from '../../server/tools/coding-tools.js';
|
|
10
|
+
import { execTools } from '../../server/tools/exec-tools.js';
|
|
11
|
+
import { filesTools } from '../../server/tools/files-tools.js';
|
|
12
|
+
import { utilsTools } from '../../server/tools/utils-tools.js';
|
|
13
|
+
let cliVersion = '0.0.0';
|
|
14
|
+
try {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
16
|
+
cliVersion = require('../../../package.json').version ?? cliVersion;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
/* compiled build may not have the package.json alongside */
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Project an internal tool export (may have extra metadata) onto the public
|
|
23
|
+
* GatewayTool shape the manifest advertises.
|
|
24
|
+
*/
|
|
25
|
+
function projectTool(t) {
|
|
26
|
+
return {
|
|
27
|
+
name: t.name,
|
|
28
|
+
description: t.description,
|
|
29
|
+
inputSchema: t.inputSchema,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Coding agents the gateway knows how to drive. Each entry maps the public
|
|
33
|
+
// agent name (used in the manifest + tool params) to the binary we'll run on
|
|
34
|
+
// PATH. Add new entries here when a new agent is supported.
|
|
35
|
+
const KNOWN_AGENTS = [
|
|
36
|
+
{ name: 'claude-code', command: 'claude' },
|
|
37
|
+
{ name: 'codex-cli', command: 'codex' },
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a bare command via the env's PATH (the same one node-pty will use
|
|
41
|
+
* when spawning). Returns the absolute path on success, null otherwise.
|
|
42
|
+
*
|
|
43
|
+
* We don't capture login PATH here because the manifest endpoint is hit very
|
|
44
|
+
* frequently; reading PATH from the process env is sufficient — the gateway
|
|
45
|
+
* is started by `corebrain gateway start` which already inherits the user's
|
|
46
|
+
* shell PATH (foreground mode) or had it captured at PtyManager load.
|
|
47
|
+
*/
|
|
48
|
+
function resolveBinary(cmd) {
|
|
49
|
+
if (cmd.includes('/'))
|
|
50
|
+
return existsSync(cmd) ? cmd : null;
|
|
51
|
+
try {
|
|
52
|
+
const out = execFileSync('/bin/sh', ['-c', `command -v ${cmd}`], {
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
timeout: 2_000,
|
|
55
|
+
});
|
|
56
|
+
const path = out.trim();
|
|
57
|
+
return path || null;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function detectAvailableAgents(configuredAgents, coding) {
|
|
64
|
+
const result = [];
|
|
65
|
+
for (const agent of KNOWN_AGENTS) {
|
|
66
|
+
// Prefer the user-configured command (often an absolute path written
|
|
67
|
+
// during `corebrain coding setup`). Falls back to a PATH lookup of the
|
|
68
|
+
// bare binary, which is unreliable for daemons launched by launchd /
|
|
69
|
+
// systemd because they don't inherit the login shell's PATH.
|
|
70
|
+
const configuredCommand = coding[agent.name]?.command;
|
|
71
|
+
const path = (configuredCommand ? resolveBinary(configuredCommand) : null) ??
|
|
72
|
+
resolveBinary(agent.command);
|
|
73
|
+
if (!path)
|
|
74
|
+
continue;
|
|
75
|
+
result.push({
|
|
76
|
+
name: agent.name,
|
|
77
|
+
command: agent.command,
|
|
78
|
+
path,
|
|
79
|
+
configured: configuredAgents.has(agent.name),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function detectDeployMode() {
|
|
85
|
+
// Explicit env wins (Dockerfile sets COREBRAIN_DEPLOY_MODE=docker).
|
|
86
|
+
const envMode = process.env.COREBRAIN_DEPLOY_MODE;
|
|
87
|
+
if (envMode === 'docker' || envMode === 'native')
|
|
88
|
+
return envMode;
|
|
89
|
+
// Fallback heuristic — `/.dockerenv` is created by Docker on container init.
|
|
90
|
+
if (existsSync('/.dockerenv'))
|
|
91
|
+
return 'docker';
|
|
92
|
+
return 'native';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A slot is considered enabled unless the user explicitly disabled it via
|
|
96
|
+
* `corebrain gateway config` (slots[name].enabled === false). Missing config
|
|
97
|
+
* means enabled, for backwards compatibility.
|
|
98
|
+
*/
|
|
99
|
+
export function isSlotEnabled(slots, slot) {
|
|
100
|
+
if (!slots)
|
|
101
|
+
return true;
|
|
102
|
+
const entry = slots[slot];
|
|
103
|
+
if (!entry)
|
|
104
|
+
return true;
|
|
105
|
+
return entry.enabled !== false;
|
|
106
|
+
}
|
|
107
|
+
export function buildManifest() {
|
|
108
|
+
const prefs = getPreferences();
|
|
109
|
+
const gw = prefs.gateway ?? {};
|
|
110
|
+
const slots = gw.slots;
|
|
111
|
+
// Respect the user's slot toggles — a disabled slot hides its tools (and
|
|
112
|
+
// agents, when coding is off) from the manifest. Callers that shouldn't
|
|
113
|
+
// see a tool shouldn't be able to hit its route either; server.ts applies
|
|
114
|
+
// the same filter when registering routes.
|
|
115
|
+
const tools = [
|
|
116
|
+
...(isSlotEnabled(slots, 'browser') ? browserTools : []),
|
|
117
|
+
...(isSlotEnabled(slots, 'coding') ? codingTools : []),
|
|
118
|
+
...(isSlotEnabled(slots, 'exec') ? execTools : []),
|
|
119
|
+
...(isSlotEnabled(slots, 'files') ? filesTools : []),
|
|
120
|
+
...utilsTools,
|
|
121
|
+
].map(projectTool);
|
|
122
|
+
// Configured coding agents — keys of prefs.coding (e.g. "claude-code", "codex-cli").
|
|
123
|
+
// Empty when the coding slot is disabled so UIs don't offer agents the user
|
|
124
|
+
// doesn't want exposed.
|
|
125
|
+
const coding = (prefs.coding ?? {});
|
|
126
|
+
const agents = isSlotEnabled(slots, 'coding') ? Object.keys(coding) : [];
|
|
127
|
+
const configuredAgents = new Set(agents);
|
|
128
|
+
const availableAgents = isSlotEnabled(slots, 'coding')
|
|
129
|
+
? detectAvailableAgents(configuredAgents, coding)
|
|
130
|
+
: [];
|
|
131
|
+
const manifest = {
|
|
132
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
133
|
+
gateway: {
|
|
134
|
+
id: gw.id ?? 'pending',
|
|
135
|
+
name: gw.name ?? `${hostname()}-gateway`,
|
|
136
|
+
version: cliVersion,
|
|
137
|
+
platform: platform(),
|
|
138
|
+
hostname: hostname(),
|
|
139
|
+
deployMode: detectDeployMode(),
|
|
140
|
+
},
|
|
141
|
+
capabilities: {
|
|
142
|
+
browser: {
|
|
143
|
+
enabled: isSlotEnabled(slots, 'browser'),
|
|
144
|
+
engines: ['chromium'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
folders: listFolders(),
|
|
148
|
+
tools,
|
|
149
|
+
agents,
|
|
150
|
+
availableAgents,
|
|
151
|
+
};
|
|
152
|
+
const etag = createHash('sha256').update(JSON.stringify(manifest)).digest('hex').slice(0, 16);
|
|
153
|
+
return { manifest, etag };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=manifest-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-builder.js","sourceRoot":"","sources":["../../../src/server/api/manifest-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../../src/server/api/ops.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAQhD,eAAO,MAAM,SAAS,EAAE,kBA6BvB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { hostname, platform } from 'node:os';
|
|
2
|
+
import { buildManifest } from './manifest-builder.js';
|
|
3
|
+
import { getPreferences } from '../../config/preferences.js';
|
|
4
|
+
const startedAt = Date.now();
|
|
5
|
+
export const opsRoutes = async (app) => {
|
|
6
|
+
app.get('/manifest', async (_req, reply) => {
|
|
7
|
+
const { manifest, etag } = buildManifest();
|
|
8
|
+
reply.header('etag', etag);
|
|
9
|
+
return manifest;
|
|
10
|
+
});
|
|
11
|
+
app.get('/healthz', async () => {
|
|
12
|
+
const { etag } = buildManifest();
|
|
13
|
+
return {
|
|
14
|
+
status: 'ok',
|
|
15
|
+
manifestEtag: etag,
|
|
16
|
+
uptimeSec: Math.floor((Date.now() - startedAt) / 1000),
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
app.get('/healthz/public', async () => {
|
|
20
|
+
return { status: 'ok' };
|
|
21
|
+
});
|
|
22
|
+
app.get('/verify', async () => {
|
|
23
|
+
const gw = getPreferences().gateway ?? {};
|
|
24
|
+
return {
|
|
25
|
+
ok: true,
|
|
26
|
+
gatewayId: gw.id ?? null,
|
|
27
|
+
hostname: hostname(),
|
|
28
|
+
platform: platform(),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../../src/server/api/ops.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAE,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE3C,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEpD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,SAAS,GAAuB,KAAK,EAAE,GAAG,EAAE,EAAE;IAC1D,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QAC1C,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAC,GAAG,aAAa,EAAE,CAAC;QACzC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3B,OAAO,QAAQ,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,EAAC,IAAI,EAAC,GAAG,aAAa,EAAE,CAAC;QAC/B,OAAO;YACN,MAAM,EAAE,IAAa;YACrB,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;SACtD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,IAAI,EAAE;QACrC,OAAO,EAAC,MAAM,EAAE,IAAa,EAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC7B,MAAM,EAAE,GAA2B,cAAc,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC;QAClE,OAAO;YACN,EAAE,EAAE,IAAI;YACR,SAAS,EAAE,EAAE,CAAC,EAAE,IAAI,IAAI;YACxB,QAAQ,EAAE,QAAQ,EAAE;YACpB,QAAQ,EAAE,QAAQ,EAAE;SACpB,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type FastifyInstance } from 'fastify';
|
|
2
|
+
export interface ApiServerOptions {
|
|
3
|
+
port: number;
|
|
4
|
+
host?: string;
|
|
5
|
+
log?: (message: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildServer(opts: ApiServerOptions): Promise<FastifyInstance>;
|
|
8
|
+
export declare function startServer(opts: ApiServerOptions): Promise<FastifyInstance>;
|
|
9
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/server/api/server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAC,KAAK,eAAe,EAAC,MAAM,SAAS,CAAC;AActD,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoDlF;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAKlF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Fastify from 'fastify';
|
|
2
|
+
import fastifyWebsocket from '@fastify/websocket';
|
|
3
|
+
import { makeAuthHook } from './auth.js';
|
|
4
|
+
import { opsRoutes } from './ops.js';
|
|
5
|
+
import { codingRoutes } from './coding/index.js';
|
|
6
|
+
import { browserRoutes } from './browser/index.js';
|
|
7
|
+
import { execRoutes } from './exec/index.js';
|
|
8
|
+
import { filesRoutes } from './files/index.js';
|
|
9
|
+
import { utilsRoutes } from './utils/index.js';
|
|
10
|
+
import { folderRoutes } from './folders/index.js';
|
|
11
|
+
import { shellRoutes } from './shell/index.js';
|
|
12
|
+
import { isSlotEnabled } from './manifest-builder.js';
|
|
13
|
+
import { getPreferences } from '../../config/preferences.js';
|
|
14
|
+
export async function buildServer(opts) {
|
|
15
|
+
const log = opts.log ?? (() => { });
|
|
16
|
+
const app = Fastify({
|
|
17
|
+
logger: false,
|
|
18
|
+
bodyLimit: 50 * 1024 * 1024, // 50 MB — browser_screenshot base64 can be large
|
|
19
|
+
trustProxy: true,
|
|
20
|
+
});
|
|
21
|
+
await app.register(fastifyWebsocket);
|
|
22
|
+
// Auth for every route except /healthz/public.
|
|
23
|
+
app.addHook('onRequest', makeAuthHook(['/healthz/public']));
|
|
24
|
+
// Ops routes are always on (manifest / healthz / verify).
|
|
25
|
+
await app.register(opsRoutes);
|
|
26
|
+
// Group routes gated by slot config — a disabled slot hides both the
|
|
27
|
+
// manifest entries and the HTTP routes so clients can't dodge the toggle.
|
|
28
|
+
const slots = getPreferences().gateway?.slots;
|
|
29
|
+
if (isSlotEnabled(slots, 'coding')) {
|
|
30
|
+
await app.register(codingRoutes, { prefix: '/api/coding' });
|
|
31
|
+
}
|
|
32
|
+
if (isSlotEnabled(slots, 'browser')) {
|
|
33
|
+
await app.register(browserRoutes, { prefix: '/api/browser' });
|
|
34
|
+
}
|
|
35
|
+
if (isSlotEnabled(slots, 'exec')) {
|
|
36
|
+
await app.register(execRoutes, { prefix: '/api/exec' });
|
|
37
|
+
}
|
|
38
|
+
if (isSlotEnabled(slots, 'files')) {
|
|
39
|
+
await app.register(filesRoutes, { prefix: '/api/files' });
|
|
40
|
+
}
|
|
41
|
+
// utils has no slot — it's always enabled (e.g. `sleep`).
|
|
42
|
+
await app.register(utilsRoutes, { prefix: '/api/utils' });
|
|
43
|
+
// Folder management — used by the webapp's per-gateway settings page to
|
|
44
|
+
// add/remove local paths or clone GitHub URLs into the workspace.
|
|
45
|
+
await app.register(folderRoutes, { prefix: '/api/folders' });
|
|
46
|
+
// General-purpose shell PTY for the webapp's Terminal tab.
|
|
47
|
+
await app.register(shellRoutes, { prefix: '/api/shell' });
|
|
48
|
+
app.setErrorHandler((err, _req, reply) => {
|
|
49
|
+
log(`api error: ${err.message}`);
|
|
50
|
+
if (reply.sent)
|
|
51
|
+
return;
|
|
52
|
+
const status = err.statusCode ?? 500;
|
|
53
|
+
reply.code(status).send({
|
|
54
|
+
ok: false,
|
|
55
|
+
error: { code: err.code ?? 'INTERNAL', message: err.message },
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
return app;
|
|
59
|
+
}
|
|
60
|
+
export async function startServer(opts) {
|
|
61
|
+
const app = await buildServer(opts);
|
|
62
|
+
await app.listen({ port: opts.port, host: opts.host ?? '0.0.0.0' });
|
|
63
|
+
opts.log?.(`gateway HTTP listening on :${opts.port}`);
|
|
64
|
+
return app;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/api/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from 'fastify';
|
|
2
|
+
/**
|
|
3
|
+
* General-purpose shell PTY for the webapp's per-gateway Terminal tab.
|
|
4
|
+
*
|
|
5
|
+
* POST /api/shell/spawn
|
|
6
|
+
* body: { cwd?: string }
|
|
7
|
+
* → 200 { ok: true, sessionId, pid }
|
|
8
|
+
*
|
|
9
|
+
* Spawns the user's `$SHELL` (falling back to `/bin/bash` → `/bin/sh`) inside
|
|
10
|
+
* a PTY managed by `ptyManager`. The browser attaches via the existing xterm
|
|
11
|
+
* WS endpoint — no CodingSession involved.
|
|
12
|
+
*
|
|
13
|
+
* Auth is handled by the global gateway auth hook (security key), so anyone
|
|
14
|
+
* able to hit this can already exec arbitrary tools — no extra guardrails.
|
|
15
|
+
*/
|
|
16
|
+
export declare const shellRoutes: FastifyPluginAsync;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/api/shell/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAOhD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,EAAE,kBA8CzB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { ptyManager } from '../../../server/pty/manager.js';
|
|
5
|
+
import { gatewayLog } from '../../../server/gateway-log.js';
|
|
6
|
+
/**
|
|
7
|
+
* General-purpose shell PTY for the webapp's per-gateway Terminal tab.
|
|
8
|
+
*
|
|
9
|
+
* POST /api/shell/spawn
|
|
10
|
+
* body: { cwd?: string }
|
|
11
|
+
* → 200 { ok: true, sessionId, pid }
|
|
12
|
+
*
|
|
13
|
+
* Spawns the user's `$SHELL` (falling back to `/bin/bash` → `/bin/sh`) inside
|
|
14
|
+
* a PTY managed by `ptyManager`. The browser attaches via the existing xterm
|
|
15
|
+
* WS endpoint — no CodingSession involved.
|
|
16
|
+
*
|
|
17
|
+
* Auth is handled by the global gateway auth hook (security key), so anyone
|
|
18
|
+
* able to hit this can already exec arbitrary tools — no extra guardrails.
|
|
19
|
+
*/
|
|
20
|
+
export const shellRoutes = async (app) => {
|
|
21
|
+
app.post('/spawn', async (req, reply) => {
|
|
22
|
+
const body = (req.body ?? {});
|
|
23
|
+
// Resolve a usable shell. SHELL → /bin/zsh → /bin/bash → /bin/sh.
|
|
24
|
+
const candidates = [
|
|
25
|
+
process.env.SHELL,
|
|
26
|
+
'/bin/zsh',
|
|
27
|
+
'/bin/bash',
|
|
28
|
+
'/bin/sh',
|
|
29
|
+
].filter((s) => Boolean(s && existsSync(s)));
|
|
30
|
+
const shell = candidates[0];
|
|
31
|
+
if (!shell) {
|
|
32
|
+
reply.code(500);
|
|
33
|
+
return { ok: false, error: 'no usable shell on PATH' };
|
|
34
|
+
}
|
|
35
|
+
const cwd = body.cwd && existsSync(body.cwd)
|
|
36
|
+
? body.cwd
|
|
37
|
+
: process.env.COREBRAIN_DEFAULT_WORKSPACE &&
|
|
38
|
+
existsSync(process.env.COREBRAIN_DEFAULT_WORKSPACE)
|
|
39
|
+
? process.env.COREBRAIN_DEFAULT_WORKSPACE
|
|
40
|
+
: homedir();
|
|
41
|
+
const sessionId = randomUUID();
|
|
42
|
+
gatewayLog(`shell spawn: shell=${shell} cwd=${cwd} sessionId=${sessionId}`);
|
|
43
|
+
try {
|
|
44
|
+
const { pid } = ptyManager.spawn({
|
|
45
|
+
sessionId,
|
|
46
|
+
command: shell,
|
|
47
|
+
args: ['-il'], // login + interactive so PATH/aliases are loaded
|
|
48
|
+
cwd,
|
|
49
|
+
agent: 'shell',
|
|
50
|
+
});
|
|
51
|
+
return { ok: true, sessionId, pid };
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
const msg = err instanceof Error ? err.message : 'spawn failed';
|
|
55
|
+
gatewayLog(`shell spawn FAILED: ${msg}`);
|
|
56
|
+
reply.code(500);
|
|
57
|
+
return { ok: false, error: msg };
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/api/shell/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AACvC,OAAO,EAAC,OAAO,EAAC,MAAM,SAAS,CAAC;AAChC,OAAO,EAAC,UAAU,EAAC,MAAM,SAAS,CAAC;AACnC,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,WAAW,GAAuB,KAAK,EAAE,GAAG,EAAE,EAAE;IAC5D,GAAG,CAAC,IAAI,CAAyB,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC/D,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAmB,CAAC;QAEhD,kEAAkE;QAClE,MAAM,UAAU,GAAG;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK;YACjB,UAAU;YACV,WAAW;YACX,SAAS;SACT,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,EAAC,CAAC;QACtD,CAAC;QAED,MAAM,GAAG,GACR,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;YAC/B,CAAC,CAAC,IAAI,CAAC,GAAG;YACV,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B;gBACtC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;gBACrD,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B;gBACzC,CAAC,CAAC,OAAO,EAAE,CAAC;QAEf,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;QAC/B,UAAU,CACT,sBAAsB,KAAK,QAAQ,GAAG,cAAc,SAAS,EAAE,CAC/D,CAAC;QAEF,IAAI,CAAC;YACJ,MAAM,EAAC,GAAG,EAAC,GAAG,UAAU,CAAC,KAAK,CAAC;gBAC9B,SAAS;gBACT,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,iDAAiD;gBAChE,GAAG;gBACH,KAAK,EAAE,OAAO;aACd,CAAC,CAAC;YACH,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;YAChE,UAAU,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAC,CAAC;QAChC,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from 'fastify';
|
|
2
|
+
interface ToolMeta {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
}
|
|
6
|
+
interface ToolResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
result?: unknown;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
type Executor = (toolName: string, params: Record<string, unknown>) => Promise<ToolResult> | ToolResult;
|
|
12
|
+
/**
|
|
13
|
+
* Build a Fastify plugin that exposes one POST route per tool in `tools`,
|
|
14
|
+
* each at path `/{tool.name}` — e.g. /api/coding/coding_ask.
|
|
15
|
+
*
|
|
16
|
+
* The plugin is meant to be registered with a prefix:
|
|
17
|
+
* app.register(makeToolGroupRoutes(codingTools, executeCodingTool), { prefix: '/api/coding' });
|
|
18
|
+
*/
|
|
19
|
+
export declare function makeToolGroupRoutes(tools: ToolMeta[], execute: Executor): FastifyPluginAsync;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=tool-group.d.ts.map
|