fraim-hub 2.0.218 → 2.0.219
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/conversation-store.js +48 -4
- package/dist/src/ai-hub/server.js +601 -50
- package/dist/src/cli/setup/ide-invocation-surfaces.js +7 -2
- package/dist/src/cli/utils/local-folder-sync.js +178 -0
- package/dist/src/cli/utils/org-publish.js +128 -0
- package/dist/src/config/persona-capability-bundles.js +34 -22
- package/dist/src/core/capability-pack.js +85 -0
- package/dist/src/services/persona-entitlement-service.js +4 -1
- package/package.json +5 -2
- package/public/ai-hub/index.html +44 -9
- package/public/ai-hub/script.js +297 -285
- package/public/ai-hub/styles.css +83 -3
- package/public/portfolio/gautam.html +2 -2
- package/public/portfolio/sam.html +3 -3
|
@@ -15,10 +15,11 @@ const conversation_store_lock_1 = require("./conversation-store-lock");
|
|
|
15
15
|
// They are NOT filesystem paths and must never be passed through path.resolve.
|
|
16
16
|
exports.MANAGER_SCOPE_KEY = '@manager';
|
|
17
17
|
exports.COMPANY_SCOPE_KEY = '@company';
|
|
18
|
-
//
|
|
18
|
+
// Fields stripped from a header (the light shape the list UI renders). Everything else
|
|
19
19
|
// (id, title, jobId, jobTitle, agentName, personaKey, status, runId, createdAt, lastUpdatedAt,
|
|
20
|
-
// scope, reviewHandoff, ...) is kept.
|
|
21
|
-
|
|
20
|
+
// scope, reviewHandoff, ...) is kept. Client-only runtime flags are omitted too so stale index
|
|
21
|
+
// cache state cannot make the frontend skip lazy body hydration.
|
|
22
|
+
const HEADER_OMITTED_FIELDS = ['messages', 'events', 'artifacts', 'run', 'delegation', '_bodyLoaded', '_stopping'];
|
|
22
23
|
/**
|
|
23
24
|
* Issue #708: resolve the conversation store bucket key for a given scope.
|
|
24
25
|
* - 'manager'/'company' → a stable sentinel key (project-independent home).
|
|
@@ -107,6 +108,44 @@ function conversationRichness(conv) {
|
|
|
107
108
|
const events = Array.isArray(value?.events) ? value.events.length : 0;
|
|
108
109
|
return messages + events;
|
|
109
110
|
}
|
|
111
|
+
function normalizedOptionalString(value) {
|
|
112
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
113
|
+
}
|
|
114
|
+
function sameOptionalField(left, right) {
|
|
115
|
+
const leftValue = normalizedOptionalString(left);
|
|
116
|
+
const rightValue = normalizedOptionalString(right);
|
|
117
|
+
return !leftValue || !rightValue || leftValue === rightValue;
|
|
118
|
+
}
|
|
119
|
+
function sameOptionalProjectPath(left, right) {
|
|
120
|
+
const leftValue = normalizedOptionalString(left);
|
|
121
|
+
const rightValue = normalizedOptionalString(right);
|
|
122
|
+
if (!leftValue || !rightValue)
|
|
123
|
+
return true;
|
|
124
|
+
return canonicalProjectPathKey(leftValue) === canonicalProjectPathKey(rightValue);
|
|
125
|
+
}
|
|
126
|
+
function conversationContinuityCompatible(left, right) {
|
|
127
|
+
const a = left;
|
|
128
|
+
const b = right;
|
|
129
|
+
if (!a || !b)
|
|
130
|
+
return true;
|
|
131
|
+
const existingSwitches = Array.isArray(a.agentSwitches) ? a.agentSwitches.length : 0;
|
|
132
|
+
const incomingSwitches = Array.isArray(b.agentSwitches) ? b.agentSwitches.length : 0;
|
|
133
|
+
if (incomingSwitches > existingSwitches)
|
|
134
|
+
return true;
|
|
135
|
+
if (!sameOptionalField(a.scope, b.scope))
|
|
136
|
+
return false;
|
|
137
|
+
if (!sameOptionalProjectPath(a.projectPath, b.projectPath))
|
|
138
|
+
return false;
|
|
139
|
+
if (!sameOptionalField(a.jobId, b.jobId))
|
|
140
|
+
return false;
|
|
141
|
+
if (!sameOptionalField(a.issueNumber, b.issueNumber))
|
|
142
|
+
return false;
|
|
143
|
+
if (!sameOptionalField(a.configuredAgentId, b.configuredAgentId))
|
|
144
|
+
return false;
|
|
145
|
+
if (!sameOptionalField(a.baseHostId, b.baseHostId))
|
|
146
|
+
return false;
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
110
149
|
// Place a raw conversation into a bucket, deduping by id. When the id already exists, keep the
|
|
111
150
|
// richer copy (more run history); tie-break on newer lastUpdatedAt. Order-independent.
|
|
112
151
|
function placeConversationInBucket(bucket, conv) {
|
|
@@ -122,6 +161,9 @@ function placeConversationInBucket(bucket, conv) {
|
|
|
122
161
|
return;
|
|
123
162
|
}
|
|
124
163
|
const existing = bucket.conversations[idx];
|
|
164
|
+
if (!conversationContinuityCompatible(existing, conv)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
125
167
|
const existingScore = conversationRichness(existing);
|
|
126
168
|
const incomingScore = conversationRichness(conv);
|
|
127
169
|
if (incomingScore > existingScore) {
|
|
@@ -223,6 +265,8 @@ function normalizeConversation(projectPath, raw) {
|
|
|
223
265
|
jobId: value.jobId,
|
|
224
266
|
agentName: value.agentName,
|
|
225
267
|
status: value.status,
|
|
268
|
+
// Issue #904: carry pauseReason explicitly so it survives the ...value spread round-trip.
|
|
269
|
+
...(value.pauseReason !== undefined && { pauseReason: value.pauseReason }),
|
|
226
270
|
createdAt: value.createdAt ?? new Date().toISOString(),
|
|
227
271
|
lastUpdatedAt: value.lastUpdatedAt ?? value.createdAt ?? new Date().toISOString(),
|
|
228
272
|
};
|
|
@@ -246,7 +290,7 @@ function newestFirst(a, b) {
|
|
|
246
290
|
}
|
|
247
291
|
function toHeader(conv) {
|
|
248
292
|
const header = { ...conv };
|
|
249
|
-
for (const field of
|
|
293
|
+
for (const field of HEADER_OMITTED_FIELDS)
|
|
250
294
|
delete header[field];
|
|
251
295
|
return header;
|
|
252
296
|
}
|