fraim-hub 2.0.308 → 2.0.310
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
CHANGED
|
@@ -630,6 +630,17 @@ function microEventFromToolResult(candidate) {
|
|
|
630
630
|
const text = resultTextFromValue(candidate.result ?? candidate.output ?? candidate.content ?? candidate.message);
|
|
631
631
|
return text ? [{ kind: 'mentor_reply', text }] : undefined;
|
|
632
632
|
}
|
|
633
|
+
function microEventFromNonMentorToolCall(candidate) {
|
|
634
|
+
const rawName = readToolName(candidate);
|
|
635
|
+
const name = typeof rawName === 'string' ? rawName : null;
|
|
636
|
+
if (!name)
|
|
637
|
+
return undefined;
|
|
638
|
+
const rawArgs = candidate.input || candidate.arguments || candidate.parameters;
|
|
639
|
+
const args = normalizeToolArgs(rawArgs);
|
|
640
|
+
const argSummary = args ? JSON.stringify(args) : '';
|
|
641
|
+
const text = argSummary ? `${name}(${argSummary})` : name;
|
|
642
|
+
return { kind: 'tool_call', text };
|
|
643
|
+
}
|
|
633
644
|
function readToolUseId(candidate) {
|
|
634
645
|
return stringValue(candidate.id) || stringValue(candidate.tool_use_id) || stringValue(candidate.toolUseId);
|
|
635
646
|
}
|
|
@@ -685,6 +696,12 @@ function parseMicroEventsSignal(line) {
|
|
|
685
696
|
if (id)
|
|
686
697
|
mentorToolUseIds.push(id);
|
|
687
698
|
}
|
|
699
|
+
else {
|
|
700
|
+
// Non-seekMentoring tool calls: emit so the manager sees all agent activity.
|
|
701
|
+
const nonMentorCall = microEventFromNonMentorToolCall(content);
|
|
702
|
+
if (nonMentorCall)
|
|
703
|
+
events.push(nonMentorCall);
|
|
704
|
+
}
|
|
688
705
|
}
|
|
689
706
|
if (content.type === 'tool_result') {
|
|
690
707
|
const reply = microEventFromToolResult(content);
|
|
@@ -698,6 +715,24 @@ function parseMicroEventsSignal(line) {
|
|
|
698
715
|
mentorToolResults.push({ toolUseId, text });
|
|
699
716
|
}
|
|
700
717
|
}
|
|
718
|
+
// Thinking blocks are suppressed from the main conversation panel but belong
|
|
719
|
+
// in micro-manage, where hidden agent reasoning is the primary signal of interest.
|
|
720
|
+
if (content.type === 'thinking' && typeof content.thinking === 'string' && content.thinking.length > 0) {
|
|
721
|
+
events.push({ kind: 'thinking', text: content.thinking });
|
|
722
|
+
}
|
|
723
|
+
// Opt-out: any content type not already handled above is emitted so new agent
|
|
724
|
+
// capabilities are visible without requiring code changes. Exclusions: types already
|
|
725
|
+
// handled (tool_use, function_call, tool_result, thinking) and 'text' (shown in the
|
|
726
|
+
// main conversation panel, not the micro-manage panel).
|
|
727
|
+
if (content.type !== 'text' &&
|
|
728
|
+
content.type !== 'tool_use' &&
|
|
729
|
+
content.type !== 'function_call' &&
|
|
730
|
+
content.type !== 'tool_result' &&
|
|
731
|
+
content.type !== 'thinking') {
|
|
732
|
+
const typeStr = typeof content.type === 'string' ? content.type : 'unknown';
|
|
733
|
+
if (typeStr)
|
|
734
|
+
events.push({ kind: 'tool_call', text: typeStr });
|
|
735
|
+
}
|
|
701
736
|
}
|
|
702
737
|
return {
|
|
703
738
|
...(events.length > 0 ? { microEvents: events } : {}),
|
|
@@ -5814,7 +5814,11 @@ class AiHubServer {
|
|
|
5814
5814
|
(0, hosts_1.createHubEvent)('system', switchEventText),
|
|
5815
5815
|
...(fallbackReason ? [(0, hosts_1.createHubEvent)('system', `Same-host resume fell back to handoff: ${fallbackReason}`)] : []),
|
|
5816
5816
|
],
|
|
5817
|
-
microEvents:
|
|
5817
|
+
microEvents: [
|
|
5818
|
+
...persistedMicroEventsForRun(conversation),
|
|
5819
|
+
createHubMicroEvent('diagnostic', 'system', switchEventText),
|
|
5820
|
+
...(fallbackReason ? [createHubMicroEvent('diagnostic', 'system', `Same-host resume fell back to handoff: ${fallbackReason}`)] : []),
|
|
5821
|
+
],
|
|
5818
5822
|
eventLogRefs: conversation.eventLogRefs || [],
|
|
5819
5823
|
currentPhase: persistedRun?.currentPhase || null,
|
|
5820
5824
|
phaseHistory: persistedRun?.phaseHistory || [],
|
|
@@ -5,7 +5,94 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.installManagedAgent = installManagedAgent;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
8
9
|
const managed_agent_paths_1 = require("./managed-agent-paths");
|
|
10
|
+
function errorMessage(error) {
|
|
11
|
+
return error instanceof Error ? error.message : 'Unknown error';
|
|
12
|
+
}
|
|
13
|
+
function isStaleNpmInstallError(error) {
|
|
14
|
+
const code = typeof error === 'object' && error !== null && 'code' in error
|
|
15
|
+
? String(error.code || '')
|
|
16
|
+
: '';
|
|
17
|
+
const message = errorMessage(error).toLowerCase();
|
|
18
|
+
return code === 'EEXIST'
|
|
19
|
+
|| message.includes('eexist')
|
|
20
|
+
|| message.includes('already exists')
|
|
21
|
+
|| message.includes('already in use');
|
|
22
|
+
}
|
|
23
|
+
function packagePathSegments(installPackage) {
|
|
24
|
+
let packageName = installPackage.trim();
|
|
25
|
+
if (!packageName)
|
|
26
|
+
return [];
|
|
27
|
+
if (packageName.startsWith('@')) {
|
|
28
|
+
const slashIndex = packageName.indexOf('/');
|
|
29
|
+
if (slashIndex === -1)
|
|
30
|
+
return [];
|
|
31
|
+
const versionAt = packageName.indexOf('@', slashIndex);
|
|
32
|
+
if (versionAt !== -1)
|
|
33
|
+
packageName = packageName.slice(0, versionAt);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const versionAt = packageName.lastIndexOf('@');
|
|
37
|
+
if (versionAt > 0)
|
|
38
|
+
packageName = packageName.slice(0, versionAt);
|
|
39
|
+
}
|
|
40
|
+
const segments = packageName.split('/');
|
|
41
|
+
return segments.every((segment) => segment && segment !== '.' && segment !== '..' && !segment.includes('\\'))
|
|
42
|
+
? segments
|
|
43
|
+
: [];
|
|
44
|
+
}
|
|
45
|
+
function isInsideDirectory(parentDir, candidate) {
|
|
46
|
+
const relative = path_1.default.relative(path_1.default.resolve(parentDir), path_1.default.resolve(candidate));
|
|
47
|
+
return !!relative && !relative.startsWith('..') && !path_1.default.isAbsolute(relative);
|
|
48
|
+
}
|
|
49
|
+
function managedShimNames(command) {
|
|
50
|
+
return process.platform === 'win32'
|
|
51
|
+
? [command, `${command}.cmd`, `${command}.ps1`]
|
|
52
|
+
: [command];
|
|
53
|
+
}
|
|
54
|
+
function cleanupManagedInstallArtifacts(option, prefix) {
|
|
55
|
+
const resolvedPrefix = path_1.default.resolve(prefix);
|
|
56
|
+
const packageSegments = packagePathSegments(option.installPackage);
|
|
57
|
+
const candidates = new Set();
|
|
58
|
+
if (packageSegments.length > 0) {
|
|
59
|
+
candidates.add(path_1.default.join(resolvedPrefix, 'node_modules', ...packageSegments));
|
|
60
|
+
candidates.add(path_1.default.join(resolvedPrefix, 'lib', 'node_modules', ...packageSegments));
|
|
61
|
+
}
|
|
62
|
+
for (const shimName of managedShimNames(option.launchCommand)) {
|
|
63
|
+
candidates.add(path_1.default.join(resolvedPrefix, shimName));
|
|
64
|
+
candidates.add(path_1.default.join(resolvedPrefix, 'bin', shimName));
|
|
65
|
+
}
|
|
66
|
+
const removed = [];
|
|
67
|
+
for (const candidate of candidates) {
|
|
68
|
+
if (!isInsideDirectory(resolvedPrefix, candidate) || !fs_1.default.existsSync(candidate))
|
|
69
|
+
continue;
|
|
70
|
+
fs_1.default.rmSync(candidate, { recursive: true, force: true });
|
|
71
|
+
removed.push(candidate);
|
|
72
|
+
}
|
|
73
|
+
return removed;
|
|
74
|
+
}
|
|
75
|
+
async function runInstallWithStaleCleanupRetry(option, prefix, runInstall) {
|
|
76
|
+
try {
|
|
77
|
+
await runInstall();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (!isStaleNpmInstallError(error))
|
|
82
|
+
throw error;
|
|
83
|
+
const removed = cleanupManagedInstallArtifacts(option, prefix);
|
|
84
|
+
try {
|
|
85
|
+
await runInstall();
|
|
86
|
+
}
|
|
87
|
+
catch (retryError) {
|
|
88
|
+
const cleanupSummary = removed.length > 0
|
|
89
|
+
? ` Removed stale managed artifacts: ${removed.join(', ')}.`
|
|
90
|
+
: ' No matching stale managed artifacts were found to remove.';
|
|
91
|
+
throw new Error(`${option.label} install hit a stale npm artifact (${errorMessage(error)}).`
|
|
92
|
+
+ `${cleanupSummary} Retry failed: ${errorMessage(retryError)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
9
96
|
// Issue #1284/#1285 (Implementation Strategy §2): the exact "standard npm
|
|
10
97
|
// global install, then fall back to FRAIM's managed prefix" sequence used to
|
|
11
98
|
// be duplicated verbatim in `server.ts` (Hub's install-agent route) and
|
|
@@ -17,6 +104,7 @@ const managed_agent_paths_1 = require("./managed-agent-paths");
|
|
|
17
104
|
// check before invoking this — it only covers the install-then-fallback path.
|
|
18
105
|
async function installManagedAgent(option, systemPath, deps) {
|
|
19
106
|
let standardInstallError = null;
|
|
107
|
+
const prefix = (0, managed_agent_paths_1.getPortableNodeBinPath)();
|
|
20
108
|
try {
|
|
21
109
|
await deps.runProcess('npm', ['install', '-g', option.installPackage], {
|
|
22
110
|
PATH: systemPath,
|
|
@@ -40,13 +128,14 @@ async function installManagedAgent(option, systemPath, deps) {
|
|
|
40
128
|
standardInstallError = `${option.label} standard install completed, but the CLI is not runnable from the user PATH.`;
|
|
41
129
|
}
|
|
42
130
|
catch (error) {
|
|
43
|
-
|
|
131
|
+
if (isStaleNpmInstallError(error))
|
|
132
|
+
cleanupManagedInstallArtifacts(option, prefix);
|
|
133
|
+
standardInstallError = errorMessage(error);
|
|
44
134
|
}
|
|
45
135
|
// Defect A fix: co-locate npm-global shims with the node.exe/npm.cmd that
|
|
46
136
|
// actually runs the install, instead of the flat legacy directory.
|
|
47
|
-
const prefix = (0, managed_agent_paths_1.getPortableNodeBinPath)();
|
|
48
137
|
fs_1.default.mkdirSync(prefix, { recursive: true });
|
|
49
|
-
await deps.runProcess('npm', ['install', '-g', option.installPackage], { npm_config_prefix: prefix });
|
|
138
|
+
await runInstallWithStaleCleanupRetry(option, prefix, () => deps.runProcess('npm', ['install', '-g', option.installPackage], { npm_config_prefix: prefix }).then(() => undefined));
|
|
50
139
|
const ver = deps.commandVersion(option.launchCommand, (0, managed_agent_paths_1.getManagedAgentBinDirs)());
|
|
51
140
|
if (!ver) {
|
|
52
141
|
throw new Error(`${option.label} install completed, but the CLI is not runnable from FRAIM's managed PATH. Standard install failure: ${standardInstallError}`);
|
|
@@ -647,6 +647,7 @@ class FirstRunSessionService {
|
|
|
647
647
|
async runNodeRow() {
|
|
648
648
|
const row = this.getRow('node');
|
|
649
649
|
if (this.embeddedDesktop) {
|
|
650
|
+
persistShellPath(this.embeddedDesktop);
|
|
650
651
|
row.status = 'ok';
|
|
651
652
|
row.verb = `${process.version} bundled with FRAIM`;
|
|
652
653
|
this.persist();
|
|
@@ -656,6 +657,7 @@ class FirstRunSessionService {
|
|
|
656
657
|
// If node is missing here something is severely wrong; fall through to error.
|
|
657
658
|
const ver = commandVersion('node');
|
|
658
659
|
if (ver) {
|
|
660
|
+
persistShellPath(this.embeddedDesktop);
|
|
659
661
|
row.status = 'ok';
|
|
660
662
|
row.verb = `${ver} installed`;
|
|
661
663
|
this.persist();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-hub",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.310",
|
|
4
4
|
"description": "FRAIM Hub local companion package.",
|
|
5
5
|
"author": "Sid Mathur <sid.mathur@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/mathursrus/FRAIM#readme",
|
|
@@ -211,7 +211,7 @@
|
|
|
211
211
|
"electron-updater": "^6.8.9",
|
|
212
212
|
"express": "^5.2.1",
|
|
213
213
|
"extract-zip": "^2.0.1",
|
|
214
|
-
"fraim": "2.0.
|
|
214
|
+
"fraim": "2.0.310",
|
|
215
215
|
"mongodb": "^7.0.0",
|
|
216
216
|
"node-cron": "4.2.1",
|
|
217
217
|
"node-edge-tts": "^1.2.10",
|
package/public/ai-hub/script.js
CHANGED
|
@@ -3632,7 +3632,10 @@ function formatMicroAuditKind(event) {
|
|
|
3632
3632
|
if (kind === 'manager_input') return 'manager';
|
|
3633
3633
|
if (kind === 'mentor_call') return 'seekMentoring call';
|
|
3634
3634
|
if (kind === 'mentor_reply') return 'mentor reply';
|
|
3635
|
+
if (kind === 'diagnostic' && event && event.channel === 'system') return 'system';
|
|
3635
3636
|
if (kind === 'diagnostic') return 'diagnostic';
|
|
3637
|
+
if (kind === 'thinking') return 'thinking';
|
|
3638
|
+
if (kind === 'tool_call') return 'tool call';
|
|
3636
3639
|
return event && event.channel ? event.channel : 'system';
|
|
3637
3640
|
}
|
|
3638
3641
|
|