fraim-framework 2.0.183 → 2.0.185
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/desktop-main.js +2 -10
- package/dist/src/ai-hub/hosts.js +1 -1
- package/dist/src/ai-hub/manager-turns.js +2 -2
- package/dist/src/ai-hub/preferences.js +3 -2
- package/dist/src/ai-hub/remote-hub-gateway.js +88 -0
- package/dist/src/ai-hub/server.js +119 -184
- package/dist/src/api/ai-hub/manager-team.js +93 -0
- package/dist/src/cli/distribution/marketplace-bundles.js +26 -27
- package/dist/src/fraim/db-service.js +25 -3
- package/dist/src/routes/oauth-routes.js +40 -5
- package/dist/src/services/account-provisioning.js +38 -0
- package/dist/src/services/admin-service.js +10 -36
- package/package.json +1 -1
- package/public/ai-hub/index.html +77 -90
- package/public/ai-hub/review.css +4 -2
- package/public/ai-hub/script.js +526 -562
- package/public/ai-hub/styles.css +151 -35
|
@@ -21,15 +21,6 @@ let isQuitting = false; // distinguishes window-close (→ tray) from app-quit
|
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
22
22
|
// Helpers
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
|
-
function tryCreateDbService() {
|
|
25
|
-
try {
|
|
26
|
-
const loaded = require('../fraim/db-service');
|
|
27
|
-
return new loaded.FraimDbService();
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
24
|
function preferredWindowSize() {
|
|
34
25
|
const { workAreaSize } = electron_1.screen.getPrimaryDisplay();
|
|
35
26
|
return {
|
|
@@ -255,7 +246,8 @@ async function launchDesktopShell(options) {
|
|
|
255
246
|
const certBundle = await (0, cert_store_1.loadOrCreateCert)();
|
|
256
247
|
server = new server_1.AiHubServer({
|
|
257
248
|
projectPath: options.projectPath,
|
|
258
|
-
|
|
249
|
+
// Issue #701: no local DB. Persona/manager-team state resolves through the hosted
|
|
250
|
+
// server via the Hub's default remote gateway (authenticated by the user's API key).
|
|
259
251
|
httpsPort,
|
|
260
252
|
certBundle,
|
|
261
253
|
folderPicker: async () => {
|
package/dist/src/ai-hub/hosts.js
CHANGED
|
@@ -592,7 +592,7 @@ function parseFraimInvocation(message) {
|
|
|
592
592
|
const trimmed = message.trim();
|
|
593
593
|
if (!trimmed)
|
|
594
594
|
return null;
|
|
595
|
-
const match = trimmed.match(/^[
|
|
595
|
+
const match = trimmed.match(/^[$/@]fraim(?:\s+(\S+))?\s*([\s\S]*)$/);
|
|
596
596
|
if (!match)
|
|
597
597
|
return null;
|
|
598
598
|
return {
|
|
@@ -6,14 +6,14 @@ exports.buildCommunicationStyleNote = buildCommunicationStyleNote;
|
|
|
6
6
|
exports.buildManagerMessage = buildManagerMessage;
|
|
7
7
|
function extractExplicitFraimInvocation(text) {
|
|
8
8
|
const raw = String(text || '');
|
|
9
|
-
const match = raw.match(/(?:^|\n|\s)([
|
|
9
|
+
const match = raw.match(/(?:^|\n|\s)([$/@]fraim)\s+([a-z0-9][a-z0-9-]*)(?=\s|$)/i);
|
|
10
10
|
if (!match || match.index == null)
|
|
11
11
|
return null;
|
|
12
12
|
const before = raw.slice(0, match.index).trim();
|
|
13
13
|
const after = raw.slice(match.index + match[0].length).trim();
|
|
14
14
|
const remainder = [before, after].filter(Boolean).join('\n\n').trim();
|
|
15
15
|
return {
|
|
16
|
-
symbol: match[1].toLowerCase()
|
|
16
|
+
symbol: match[1].toLowerCase(),
|
|
17
17
|
jobId: match[2].toLowerCase(),
|
|
18
18
|
remainder,
|
|
19
19
|
};
|
|
@@ -68,8 +68,10 @@ function normalizeProjectEntry(raw, fallbackPath) {
|
|
|
68
68
|
return null;
|
|
69
69
|
const folderPath = normalizeProjectPath(rawPath);
|
|
70
70
|
const basename = path_1.default.basename(folderPath) || folderPath;
|
|
71
|
-
const team = Array.isArray(value.team) ? value.team.filter((entry) => typeof entry === 'string') : [];
|
|
72
71
|
const rawId = typeof value.id === 'string' ? value.id.trim() : '';
|
|
72
|
+
// The employee roster is deliberately dropped here (not read, not persisted):
|
|
73
|
+
// it is derived from the bootstrap's hired personas at render time so it stays
|
|
74
|
+
// consistent across machines. Any `team` on incoming/legacy state is discarded.
|
|
73
75
|
return {
|
|
74
76
|
id: rawId || projectIdForPath(folderPath),
|
|
75
77
|
name: typeof value.name === 'string' && value.name.length > 0 ? value.name : basename,
|
|
@@ -78,7 +80,6 @@ function normalizeProjectEntry(raw, fallbackPath) {
|
|
|
78
80
|
outcome: typeof value.outcome === 'string' ? value.outcome : '',
|
|
79
81
|
rules: typeof value.rules === 'string' ? value.rules : '',
|
|
80
82
|
brief: typeof value.brief === 'string' ? value.brief : (typeof value.intent === 'string' ? value.intent : ''),
|
|
81
|
-
team,
|
|
82
83
|
updatedAt: typeof value.updatedAt === 'string' ? value.updatedAt : undefined,
|
|
83
84
|
};
|
|
84
85
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HttpHubRemoteGateway = void 0;
|
|
7
|
+
exports.resolveFraimRemoteUrl = resolveFraimRemoteUrl;
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
function resolveFraimRemoteUrl(explicit) {
|
|
10
|
+
return (explicit || process.env.FRAIM_REMOTE_URL || 'https://fraim.wellnessatwork.me').replace(/\/+$/, '');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Default HTTP-backed gateway. Mirrors the ProviderClient axios pattern:
|
|
14
|
+
* base URL from FRAIM_REMOTE_URL, `x-api-key` auth header, 10s timeout.
|
|
15
|
+
*/
|
|
16
|
+
class HttpHubRemoteGateway {
|
|
17
|
+
constructor(serverUrl) {
|
|
18
|
+
this.baseURL = resolveFraimRemoteUrl(serverUrl);
|
|
19
|
+
}
|
|
20
|
+
client(apiKey) {
|
|
21
|
+
return axios_1.default.create({
|
|
22
|
+
baseURL: this.baseURL,
|
|
23
|
+
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
|
|
24
|
+
timeout: 10000,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async getPersonaState(apiKey) {
|
|
28
|
+
if (!apiKey)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
const res = await this.client(apiKey).get('/api/personas/me');
|
|
32
|
+
return res.data;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
// 401 (no/expired key) or 404 (feature disabled) => treat as "no state" so the Hub
|
|
36
|
+
// renders a clean locked/not-signed-in view instead of crashing.
|
|
37
|
+
const status = err?.response?.status;
|
|
38
|
+
if (status === 401 || status === 404)
|
|
39
|
+
return null;
|
|
40
|
+
console.warn('[ai-hub] getPersonaState failed:', err?.message || err);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async listManagerTeam(apiKey) {
|
|
45
|
+
if (!apiKey)
|
|
46
|
+
return [];
|
|
47
|
+
try {
|
|
48
|
+
const res = await this.client(apiKey).get('/api/ai-hub/manager-team');
|
|
49
|
+
const team = (res.data?.team ?? []);
|
|
50
|
+
return Array.isArray(team) ? team : [];
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const status = err?.response?.status;
|
|
54
|
+
if (status === 401 || status === 404)
|
|
55
|
+
return [];
|
|
56
|
+
console.warn('[ai-hub] listManagerTeam failed:', err?.message || err);
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async assignManagerTeam(apiKey, personaKey) {
|
|
61
|
+
if (!apiKey)
|
|
62
|
+
return { status: 401, body: { error: 'authentication_required' } };
|
|
63
|
+
try {
|
|
64
|
+
const res = await this.client(apiKey).post('/api/ai-hub/manager-team/assign', { personaKey });
|
|
65
|
+
return { status: res.status, body: res.data };
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
if (err?.response)
|
|
69
|
+
return { status: err.response.status, body: err.response.data };
|
|
70
|
+
console.warn('[ai-hub] assignManagerTeam failed:', err?.message || err);
|
|
71
|
+
return { status: 500, body: { error: 'internal_error' } };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async removeManagerTeam(apiKey, personaKey) {
|
|
75
|
+
if (!apiKey)
|
|
76
|
+
return;
|
|
77
|
+
try {
|
|
78
|
+
await this.client(apiKey).delete(`/api/ai-hub/manager-team/assign/${encodeURIComponent(personaKey)}`);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const status = err?.response?.status;
|
|
82
|
+
if (status === 401 || status === 404)
|
|
83
|
+
return;
|
|
84
|
+
console.warn('[ai-hub] removeManagerTeam failed:', err?.message || err);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.HttpHubRemoteGateway = HttpHubRemoteGateway;
|