fraim 2.0.140 → 2.0.142
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/ai-hub/hosts.js +54 -4
- package/package.json +1 -1
package/dist/src/ai-hub/hosts.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.createHubEvent = exports.createHubMessage = exports.ScriptedHostRuntime = exports.FakeHostRuntime = exports.CliHostRuntime = void 0;
|
|
4
7
|
exports.parseSeekMentoringSignal = parseSeekMentoringSignal;
|
|
@@ -10,6 +13,9 @@ exports.buildContinuePlan = buildContinuePlan;
|
|
|
10
13
|
exports.parseHostLine = parseHostLine;
|
|
11
14
|
const crypto_1 = require("crypto");
|
|
12
15
|
const child_process_1 = require("child_process");
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const os_1 = __importDefault(require("os"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
13
19
|
// Parse a single line of host stdout looking for a seekMentoring tool-use
|
|
14
20
|
// signal. Returns null if the line does not contain one. Supports both
|
|
15
21
|
// hosts FRAIM ships against today:
|
|
@@ -247,19 +253,63 @@ function detectEmployees() {
|
|
|
247
253
|
};
|
|
248
254
|
});
|
|
249
255
|
}
|
|
256
|
+
// Rewrite a /fraim or $fraim job invocation to a direct MCP tool call instruction.
|
|
257
|
+
// Gemini CLI has a /fraim command but it conflicts when both workspace-level and
|
|
258
|
+
// user-level fraim.toml commands exist (Gemini renames both), making /fraim
|
|
259
|
+
// unrecognised. Sending an explicit get_fraim_job instruction bypasses the slash
|
|
260
|
+
// command entirely and works regardless of whether the command exists.
|
|
261
|
+
function transformGeminiMessage(message) {
|
|
262
|
+
const match = message.match(/^[/$]fraim\s+(\S+)\n?([\s\S]*)$/);
|
|
263
|
+
if (!match)
|
|
264
|
+
return message;
|
|
265
|
+
const jobId = match[1];
|
|
266
|
+
const instructions = match[2].trim();
|
|
267
|
+
const parts = [
|
|
268
|
+
`Call the get_fraim_job MCP tool with job "${jobId}" to get the full job instructions, then follow them exactly.`,
|
|
269
|
+
];
|
|
270
|
+
if (instructions)
|
|
271
|
+
parts.push(`\n\nUser instructions: ${instructions}`);
|
|
272
|
+
return parts.join('');
|
|
273
|
+
}
|
|
274
|
+
// If ~/.gemini/settings.json has a wrong/test FRAIM_API_KEY, patch it with the
|
|
275
|
+
// real key from ~/.fraim/config.json so the FRAIM MCP server can authenticate.
|
|
276
|
+
// This self-heals when a test run accidentally writes a test key to global config.
|
|
277
|
+
function ensureGeminiApiKey() {
|
|
278
|
+
try {
|
|
279
|
+
const home = os_1.default.homedir();
|
|
280
|
+
const fraimConfigPath = path_1.default.join(home, '.fraim', 'config.json');
|
|
281
|
+
const geminiSettingsPath = path_1.default.join(home, '.gemini', 'settings.json');
|
|
282
|
+
if (!fs_1.default.existsSync(fraimConfigPath) || !fs_1.default.existsSync(geminiSettingsPath))
|
|
283
|
+
return;
|
|
284
|
+
const fraim = JSON.parse(fs_1.default.readFileSync(fraimConfigPath, 'utf8'));
|
|
285
|
+
const realKey = fraim.apiKey;
|
|
286
|
+
if (!realKey)
|
|
287
|
+
return;
|
|
288
|
+
const settings = JSON.parse(fs_1.default.readFileSync(geminiSettingsPath, 'utf8'));
|
|
289
|
+
const fraimServer = settings?.mcpServers?.fraim;
|
|
290
|
+
if (!fraimServer?.env)
|
|
291
|
+
return;
|
|
292
|
+
if (fraimServer.env.FRAIM_API_KEY !== realKey) {
|
|
293
|
+
fraimServer.env.FRAIM_API_KEY = realKey;
|
|
294
|
+
fs_1.default.writeFileSync(geminiSettingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
catch { /* best-effort: never crash the Hub over a config patch */ }
|
|
298
|
+
}
|
|
250
299
|
function buildStartPlan(hostId, message) {
|
|
251
300
|
if (hostId === 'codex') {
|
|
252
301
|
return {
|
|
253
302
|
command: executableName('codex'),
|
|
254
|
-
args: ['exec', '--json', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox', '--model', '
|
|
303
|
+
args: ['exec', '--json', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox', '--model', 'o4-mini'],
|
|
255
304
|
stdin: message,
|
|
256
305
|
};
|
|
257
306
|
}
|
|
258
307
|
if (hostId === 'gemini') {
|
|
308
|
+
ensureGeminiApiKey();
|
|
259
309
|
return {
|
|
260
310
|
command: executableName('gemini'),
|
|
261
311
|
args: ['--yolo', '--skip-trust'],
|
|
262
|
-
stdin: message,
|
|
312
|
+
stdin: transformGeminiMessage(message),
|
|
263
313
|
};
|
|
264
314
|
}
|
|
265
315
|
return {
|
|
@@ -272,7 +322,7 @@ function buildContinuePlan(hostId, sessionId, message) {
|
|
|
272
322
|
if (hostId === 'codex') {
|
|
273
323
|
return {
|
|
274
324
|
command: executableName('codex'),
|
|
275
|
-
args: ['exec', 'resume', '--json', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox', '--model', '
|
|
325
|
+
args: ['exec', 'resume', '--json', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox', '--model', 'o4-mini', sessionId],
|
|
276
326
|
stdin: message,
|
|
277
327
|
};
|
|
278
328
|
}
|
|
@@ -387,7 +437,7 @@ function spawnHostProcess(hostId, plan, projectPath, handlers) {
|
|
|
387
437
|
const child = (0, child_process_1.spawn)(invocation.command, invocation.args, {
|
|
388
438
|
cwd: projectPath,
|
|
389
439
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
390
|
-
env: process.env,
|
|
440
|
+
env: plan.env ? { ...process.env, ...plan.env } : process.env,
|
|
391
441
|
});
|
|
392
442
|
if (typeof plan.stdin === 'string') {
|
|
393
443
|
child.stdin.write(plan.stdin);
|