chainlesschain 0.143.0 → 0.145.0
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/package.json +1 -1
- package/src/commands/a2a.js +196 -28
- package/src/commands/activitypub.js +157 -27
- package/src/commands/agent.js +587 -103
- package/src/commands/audit.js +206 -0
- package/src/commands/bi.js +152 -27
- package/src/commands/bm25.js +111 -27
- package/src/commands/browse.js +190 -29
- package/src/commands/ccron.js +128 -28
- package/src/commands/chat.js +207 -0
- package/src/commands/compliance.js +414 -34
- package/src/commands/compt.js +127 -29
- package/src/commands/consol.js +8 -2
- package/src/commands/cowork.js +580 -34
- package/src/commands/crosschain.js +182 -28
- package/src/commands/dao.js +182 -28
- package/src/commands/dlp.js +172 -27
- package/src/commands/economy.js +205 -50
- package/src/commands/evolution.js +203 -50
- package/src/commands/evomap.js +182 -27
- package/src/commands/fflag.js +74 -22
- package/src/commands/git.js +177 -37
- package/src/commands/hardening.js +209 -0
- package/src/commands/hmemory.js +204 -50
- package/src/commands/incentive.js +209 -0
- package/src/commands/inference.js +170 -34
- package/src/commands/itbudget.js +149 -33
- package/src/commands/kg.js +206 -0
- package/src/commands/lowcode.js +195 -38
- package/src/commands/marketplace.js +206 -0
- package/src/commands/matrix.js +179 -27
- package/src/commands/mcpscaf.js +145 -33
- package/src/commands/meminj.js +145 -33
- package/src/commands/nostr.js +178 -27
- package/src/commands/orchestrate.js +217 -0
- package/src/commands/orchgov.js +144 -33
- package/src/commands/pdfp.js +109 -27
- package/src/commands/perf.js +169 -32
- package/src/commands/perm.js +144 -33
- package/src/commands/pipeline.js +207 -52
- package/src/commands/planmode.js +141 -32
- package/src/commands/privacy.js +203 -0
- package/src/commands/promcomp.js +111 -27
- package/src/commands/recommend.js +177 -34
- package/src/commands/reputation.js +208 -0
- package/src/commands/sandbox.js +206 -0
- package/src/commands/seshhook.js +145 -33
- package/src/commands/seshsearch.js +141 -33
- package/src/commands/seshtail.js +144 -33
- package/src/commands/seshu.js +152 -33
- package/src/commands/sganal.js +123 -29
- package/src/commands/siem.js +201 -34
- package/src/commands/sla.js +212 -0
- package/src/commands/slotfill.js +146 -33
- package/src/commands/social.js +157 -32
- package/src/commands/stress.js +206 -0
- package/src/commands/svccont.js +145 -33
- package/src/commands/terraform.js +206 -0
- package/src/commands/tms.js +171 -33
- package/src/commands/topiccls.js +146 -33
- package/src/commands/uprof.js +141 -32
- package/src/commands/vcheck.js +122 -28
- package/src/commands/webfetch.js +141 -32
- package/src/commands/zkp.js +184 -28
- package/src/index.js +40 -0
- package/src/lib/a2a-protocol.js +319 -51
- package/src/lib/activitypub-bridge.js +288 -50
- package/src/lib/agent-economy.js +304 -51
- package/src/lib/app-builder.js +279 -46
- package/src/lib/audit-logger.js +321 -0
- package/src/lib/autonomous-agent.js +284 -48
- package/src/lib/bi-engine.js +283 -49
- package/src/lib/bm25-search.js +301 -49
- package/src/lib/browser-automation.js +296 -49
- package/src/lib/chat-core.js +336 -0
- package/src/lib/claude-code-bridge.js +341 -0
- package/src/lib/compliance-framework-reporter.js +305 -51
- package/src/lib/compliance-manager.js +330 -0
- package/src/lib/compression-telemetry.js +301 -49
- package/src/lib/content-recommender.js +317 -52
- package/src/lib/cowork-cron.js +298 -49
- package/src/lib/cowork-learning.js +333 -0
- package/src/lib/cowork-task-runner.js +308 -51
- package/src/lib/cowork-workflow.js +327 -0
- package/src/lib/cross-chain.js +311 -51
- package/src/lib/dao-governance.js +280 -46
- package/src/lib/dlp-engine.js +287 -49
- package/src/lib/evolution-system.js +278 -47
- package/src/lib/evomap-manager.js +280 -46
- package/src/lib/execution-backend.js +294 -48
- package/src/lib/feature-flags.js +294 -49
- package/src/lib/git-integration.js +285 -47
- package/src/lib/hardening-manager.js +341 -0
- package/src/lib/hierarchical-memory.js +284 -48
- package/src/lib/inference-network.js +308 -51
- package/src/lib/iteration-budget.js +302 -50
- package/src/lib/knowledge-graph.js +333 -0
- package/src/lib/matrix-bridge.js +281 -47
- package/src/lib/mcp-scaffold.js +318 -54
- package/src/lib/memory-injection.js +288 -49
- package/src/lib/nostr-bridge.js +286 -49
- package/src/lib/orchestrator.js +293 -48
- package/src/lib/pdf-parser.js +298 -49
- package/src/lib/perf-tuning.js +309 -50
- package/src/lib/permission-engine.js +287 -49
- package/src/lib/pipeline-orchestrator.js +289 -49
- package/src/lib/plan-mode.js +298 -51
- package/src/lib/privacy-computing.js +335 -0
- package/src/lib/reputation-optimizer.js +340 -0
- package/src/lib/sandbox-v2.js +327 -0
- package/src/lib/service-container.js +313 -52
- package/src/lib/session-consolidator.js +296 -49
- package/src/lib/session-hooks.js +312 -53
- package/src/lib/session-search.js +304 -51
- package/src/lib/session-tail.js +288 -49
- package/src/lib/session-usage.js +298 -52
- package/src/lib/siem-exporter.js +298 -51
- package/src/lib/skill-marketplace.js +345 -0
- package/src/lib/sla-manager.js +341 -0
- package/src/lib/slot-filler.js +303 -51
- package/src/lib/social-graph-analytics.js +295 -49
- package/src/lib/social-graph.js +272 -49
- package/src/lib/stress-tester.js +342 -0
- package/src/lib/sub-agent-registry.js +302 -53
- package/src/lib/task-model-selector.js +302 -50
- package/src/lib/terraform-manager.js +333 -0
- package/src/lib/todo-manager.js +281 -47
- package/src/lib/token-incentive.js +341 -0
- package/src/lib/topic-classifier.js +297 -49
- package/src/lib/user-profile.js +294 -50
- package/src/lib/version-checker.js +304 -50
- package/src/lib/web-fetch.js +292 -51
- package/src/lib/zkp-engine.js +286 -49
|
@@ -204,25 +204,62 @@ export class CLIContentRecommender {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
|
|
208
207
|
// ===== V2 Surface: Content Recommender governance overlay (CLI v0.139.0) =====
|
|
209
208
|
export const RECOMMENDER_PROFILE_MATURITY_V2 = Object.freeze({
|
|
210
|
-
PENDING: "pending",
|
|
209
|
+
PENDING: "pending",
|
|
210
|
+
ACTIVE: "active",
|
|
211
|
+
STALE: "stale",
|
|
212
|
+
ARCHIVED: "archived",
|
|
211
213
|
});
|
|
212
214
|
export const RECOMMENDATION_JOB_LIFECYCLE_V2 = Object.freeze({
|
|
213
|
-
QUEUED: "queued",
|
|
215
|
+
QUEUED: "queued",
|
|
216
|
+
RUNNING: "running",
|
|
217
|
+
COMPLETED: "completed",
|
|
218
|
+
FAILED: "failed",
|
|
219
|
+
CANCELLED: "cancelled",
|
|
214
220
|
});
|
|
215
221
|
|
|
216
222
|
const _crpTrans = new Map([
|
|
217
|
-
[
|
|
218
|
-
|
|
219
|
-
|
|
223
|
+
[
|
|
224
|
+
RECOMMENDER_PROFILE_MATURITY_V2.PENDING,
|
|
225
|
+
new Set([
|
|
226
|
+
RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE,
|
|
227
|
+
RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED,
|
|
228
|
+
]),
|
|
229
|
+
],
|
|
230
|
+
[
|
|
231
|
+
RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE,
|
|
232
|
+
new Set([
|
|
233
|
+
RECOMMENDER_PROFILE_MATURITY_V2.STALE,
|
|
234
|
+
RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED,
|
|
235
|
+
]),
|
|
236
|
+
],
|
|
237
|
+
[
|
|
238
|
+
RECOMMENDER_PROFILE_MATURITY_V2.STALE,
|
|
239
|
+
new Set([
|
|
240
|
+
RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE,
|
|
241
|
+
RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED,
|
|
242
|
+
]),
|
|
243
|
+
],
|
|
220
244
|
[RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED, new Set()],
|
|
221
245
|
]);
|
|
222
246
|
const _crpTerminal = new Set([RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED]);
|
|
223
247
|
const _crjTrans = new Map([
|
|
224
|
-
[
|
|
225
|
-
|
|
248
|
+
[
|
|
249
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.QUEUED,
|
|
250
|
+
new Set([
|
|
251
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.RUNNING,
|
|
252
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.CANCELLED,
|
|
253
|
+
]),
|
|
254
|
+
],
|
|
255
|
+
[
|
|
256
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.RUNNING,
|
|
257
|
+
new Set([
|
|
258
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.COMPLETED,
|
|
259
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.FAILED,
|
|
260
|
+
RECOMMENDATION_JOB_LIFECYCLE_V2.CANCELLED,
|
|
261
|
+
]),
|
|
262
|
+
],
|
|
226
263
|
[RECOMMENDATION_JOB_LIFECYCLE_V2.COMPLETED, new Set()],
|
|
227
264
|
[RECOMMENDATION_JOB_LIFECYCLE_V2.FAILED, new Set()],
|
|
228
265
|
[RECOMMENDATION_JOB_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
@@ -235,76 +272,304 @@ let _crpMaxPendingJobsPerProfile = 10;
|
|
|
235
272
|
let _crpIdleMs = 7 * 24 * 60 * 60 * 1000;
|
|
236
273
|
let _crjStuckMs = 5 * 60 * 1000;
|
|
237
274
|
|
|
238
|
-
function _crpPos(n, lbl) {
|
|
275
|
+
function _crpPos(n, lbl) {
|
|
276
|
+
const v = Math.floor(Number(n));
|
|
277
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
278
|
+
throw new Error(`${lbl} must be positive integer`);
|
|
279
|
+
return v;
|
|
280
|
+
}
|
|
239
281
|
|
|
240
|
-
export function setMaxActiveRecommenderProfilesPerOwnerV2(n) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
export function
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
export function
|
|
247
|
-
|
|
282
|
+
export function setMaxActiveRecommenderProfilesPerOwnerV2(n) {
|
|
283
|
+
_crpMaxActivePerOwner = _crpPos(n, "maxActiveRecommenderProfilesPerOwner");
|
|
284
|
+
}
|
|
285
|
+
export function getMaxActiveRecommenderProfilesPerOwnerV2() {
|
|
286
|
+
return _crpMaxActivePerOwner;
|
|
287
|
+
}
|
|
288
|
+
export function setMaxPendingRecommendationJobsPerProfileV2(n) {
|
|
289
|
+
_crpMaxPendingJobsPerProfile = _crpPos(
|
|
290
|
+
n,
|
|
291
|
+
"maxPendingRecommendationJobsPerProfile",
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
export function getMaxPendingRecommendationJobsPerProfileV2() {
|
|
295
|
+
return _crpMaxPendingJobsPerProfile;
|
|
296
|
+
}
|
|
297
|
+
export function setRecommenderProfileIdleMsV2(n) {
|
|
298
|
+
_crpIdleMs = _crpPos(n, "recommenderProfileIdleMs");
|
|
299
|
+
}
|
|
300
|
+
export function getRecommenderProfileIdleMsV2() {
|
|
301
|
+
return _crpIdleMs;
|
|
302
|
+
}
|
|
303
|
+
export function setRecommendationJobStuckMsV2(n) {
|
|
304
|
+
_crjStuckMs = _crpPos(n, "recommendationJobStuckMs");
|
|
305
|
+
}
|
|
306
|
+
export function getRecommendationJobStuckMsV2() {
|
|
307
|
+
return _crjStuckMs;
|
|
308
|
+
}
|
|
248
309
|
|
|
249
310
|
export function _resetStateContentRecommenderV2() {
|
|
250
|
-
_crpsV2.clear();
|
|
251
|
-
|
|
252
|
-
|
|
311
|
+
_crpsV2.clear();
|
|
312
|
+
_crjsV2.clear();
|
|
313
|
+
_crpMaxActivePerOwner = 8;
|
|
314
|
+
_crpMaxPendingJobsPerProfile = 10;
|
|
315
|
+
_crpIdleMs = 7 * 24 * 60 * 60 * 1000;
|
|
316
|
+
_crjStuckMs = 5 * 60 * 1000;
|
|
253
317
|
}
|
|
254
318
|
|
|
255
|
-
export function registerRecommenderProfileV2({
|
|
319
|
+
export function registerRecommenderProfileV2({
|
|
320
|
+
id,
|
|
321
|
+
owner,
|
|
322
|
+
strategy,
|
|
323
|
+
metadata,
|
|
324
|
+
} = {}) {
|
|
256
325
|
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
257
326
|
if (!owner || typeof owner !== "string") throw new Error("owner is required");
|
|
258
|
-
if (_crpsV2.has(id))
|
|
327
|
+
if (_crpsV2.has(id))
|
|
328
|
+
throw new Error(`recommender profile ${id} already registered`);
|
|
259
329
|
const now = Date.now();
|
|
260
|
-
const p = {
|
|
330
|
+
const p = {
|
|
331
|
+
id,
|
|
332
|
+
owner,
|
|
333
|
+
strategy: strategy || "tfidf",
|
|
334
|
+
status: RECOMMENDER_PROFILE_MATURITY_V2.PENDING,
|
|
335
|
+
createdAt: now,
|
|
336
|
+
updatedAt: now,
|
|
337
|
+
activatedAt: null,
|
|
338
|
+
archivedAt: null,
|
|
339
|
+
lastTouchedAt: now,
|
|
340
|
+
metadata: { ...(metadata || {}) },
|
|
341
|
+
};
|
|
261
342
|
_crpsV2.set(id, p);
|
|
262
343
|
return { ...p, metadata: { ...p.metadata } };
|
|
263
344
|
}
|
|
264
|
-
function _crpCheckP(from, to) {
|
|
265
|
-
|
|
345
|
+
function _crpCheckP(from, to) {
|
|
346
|
+
const a = _crpTrans.get(from);
|
|
347
|
+
if (!a || !a.has(to))
|
|
348
|
+
throw new Error(`invalid recommender profile transition ${from} → ${to}`);
|
|
349
|
+
}
|
|
350
|
+
function _crpCountActive(owner) {
|
|
351
|
+
let n = 0;
|
|
352
|
+
for (const p of _crpsV2.values())
|
|
353
|
+
if (
|
|
354
|
+
p.owner === owner &&
|
|
355
|
+
p.status === RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE
|
|
356
|
+
)
|
|
357
|
+
n++;
|
|
358
|
+
return n;
|
|
359
|
+
}
|
|
266
360
|
|
|
267
361
|
export function activateRecommenderProfileV2(id) {
|
|
268
|
-
const p = _crpsV2.get(id);
|
|
362
|
+
const p = _crpsV2.get(id);
|
|
363
|
+
if (!p) throw new Error(`recommender profile ${id} not found`);
|
|
269
364
|
_crpCheckP(p.status, RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE);
|
|
270
365
|
const recovery = p.status === RECOMMENDER_PROFILE_MATURITY_V2.STALE;
|
|
271
|
-
if (!recovery) {
|
|
272
|
-
|
|
366
|
+
if (!recovery) {
|
|
367
|
+
const c = _crpCountActive(p.owner);
|
|
368
|
+
if (c >= _crpMaxActivePerOwner)
|
|
369
|
+
throw new Error(
|
|
370
|
+
`max active recommender profiles per owner (${_crpMaxActivePerOwner}) reached for ${p.owner}`,
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
const now = Date.now();
|
|
374
|
+
p.status = RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE;
|
|
375
|
+
p.updatedAt = now;
|
|
376
|
+
p.lastTouchedAt = now;
|
|
377
|
+
if (!p.activatedAt) p.activatedAt = now;
|
|
378
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
379
|
+
}
|
|
380
|
+
export function staleRecommenderProfileV2(id) {
|
|
381
|
+
const p = _crpsV2.get(id);
|
|
382
|
+
if (!p) throw new Error(`recommender profile ${id} not found`);
|
|
383
|
+
_crpCheckP(p.status, RECOMMENDER_PROFILE_MATURITY_V2.STALE);
|
|
384
|
+
p.status = RECOMMENDER_PROFILE_MATURITY_V2.STALE;
|
|
385
|
+
p.updatedAt = Date.now();
|
|
386
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
387
|
+
}
|
|
388
|
+
export function archiveRecommenderProfileV2(id) {
|
|
389
|
+
const p = _crpsV2.get(id);
|
|
390
|
+
if (!p) throw new Error(`recommender profile ${id} not found`);
|
|
391
|
+
_crpCheckP(p.status, RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED);
|
|
392
|
+
const now = Date.now();
|
|
393
|
+
p.status = RECOMMENDER_PROFILE_MATURITY_V2.ARCHIVED;
|
|
394
|
+
p.updatedAt = now;
|
|
395
|
+
if (!p.archivedAt) p.archivedAt = now;
|
|
396
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
397
|
+
}
|
|
398
|
+
export function touchRecommenderProfileV2(id) {
|
|
399
|
+
const p = _crpsV2.get(id);
|
|
400
|
+
if (!p) throw new Error(`recommender profile ${id} not found`);
|
|
401
|
+
if (_crpTerminal.has(p.status))
|
|
402
|
+
throw new Error(`cannot touch terminal recommender profile ${id}`);
|
|
403
|
+
const now = Date.now();
|
|
404
|
+
p.lastTouchedAt = now;
|
|
405
|
+
p.updatedAt = now;
|
|
406
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
407
|
+
}
|
|
408
|
+
export function getRecommenderProfileV2(id) {
|
|
409
|
+
const p = _crpsV2.get(id);
|
|
410
|
+
if (!p) return null;
|
|
273
411
|
return { ...p, metadata: { ...p.metadata } };
|
|
274
412
|
}
|
|
275
|
-
export function
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
413
|
+
export function listRecommenderProfilesV2() {
|
|
414
|
+
return [..._crpsV2.values()].map((p) => ({
|
|
415
|
+
...p,
|
|
416
|
+
metadata: { ...p.metadata },
|
|
417
|
+
}));
|
|
418
|
+
}
|
|
280
419
|
|
|
281
|
-
function _crjCountPending(profileId) {
|
|
420
|
+
function _crjCountPending(profileId) {
|
|
421
|
+
let n = 0;
|
|
422
|
+
for (const j of _crjsV2.values())
|
|
423
|
+
if (
|
|
424
|
+
j.profileId === profileId &&
|
|
425
|
+
(j.status === RECOMMENDATION_JOB_LIFECYCLE_V2.QUEUED ||
|
|
426
|
+
j.status === RECOMMENDATION_JOB_LIFECYCLE_V2.RUNNING)
|
|
427
|
+
)
|
|
428
|
+
n++;
|
|
429
|
+
return n;
|
|
430
|
+
}
|
|
282
431
|
|
|
283
|
-
export function createRecommendationJobV2({
|
|
432
|
+
export function createRecommendationJobV2({
|
|
433
|
+
id,
|
|
434
|
+
profileId,
|
|
435
|
+
query,
|
|
436
|
+
metadata,
|
|
437
|
+
} = {}) {
|
|
284
438
|
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
285
|
-
if (!profileId || typeof profileId !== "string")
|
|
286
|
-
|
|
287
|
-
if (
|
|
439
|
+
if (!profileId || typeof profileId !== "string")
|
|
440
|
+
throw new Error("profileId is required");
|
|
441
|
+
if (_crjsV2.has(id))
|
|
442
|
+
throw new Error(`recommendation job ${id} already exists`);
|
|
443
|
+
if (!_crpsV2.has(profileId))
|
|
444
|
+
throw new Error(`recommender profile ${profileId} not found`);
|
|
288
445
|
const pending = _crjCountPending(profileId);
|
|
289
|
-
if (pending >= _crpMaxPendingJobsPerProfile)
|
|
446
|
+
if (pending >= _crpMaxPendingJobsPerProfile)
|
|
447
|
+
throw new Error(
|
|
448
|
+
`max pending recommendation jobs per profile (${_crpMaxPendingJobsPerProfile}) reached for ${profileId}`,
|
|
449
|
+
);
|
|
290
450
|
const now = Date.now();
|
|
291
|
-
const j = {
|
|
451
|
+
const j = {
|
|
452
|
+
id,
|
|
453
|
+
profileId,
|
|
454
|
+
query: query || "",
|
|
455
|
+
status: RECOMMENDATION_JOB_LIFECYCLE_V2.QUEUED,
|
|
456
|
+
createdAt: now,
|
|
457
|
+
updatedAt: now,
|
|
458
|
+
startedAt: null,
|
|
459
|
+
settledAt: null,
|
|
460
|
+
metadata: { ...(metadata || {}) },
|
|
461
|
+
};
|
|
292
462
|
_crjsV2.set(id, j);
|
|
293
463
|
return { ...j, metadata: { ...j.metadata } };
|
|
294
464
|
}
|
|
295
|
-
function _crjCheckJ(from, to) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
export function
|
|
301
|
-
|
|
465
|
+
function _crjCheckJ(from, to) {
|
|
466
|
+
const a = _crjTrans.get(from);
|
|
467
|
+
if (!a || !a.has(to))
|
|
468
|
+
throw new Error(`invalid recommendation job transition ${from} → ${to}`);
|
|
469
|
+
}
|
|
470
|
+
export function startRecommendationJobV2(id) {
|
|
471
|
+
const j = _crjsV2.get(id);
|
|
472
|
+
if (!j) throw new Error(`recommendation job ${id} not found`);
|
|
473
|
+
_crjCheckJ(j.status, RECOMMENDATION_JOB_LIFECYCLE_V2.RUNNING);
|
|
474
|
+
const now = Date.now();
|
|
475
|
+
j.status = RECOMMENDATION_JOB_LIFECYCLE_V2.RUNNING;
|
|
476
|
+
j.updatedAt = now;
|
|
477
|
+
if (!j.startedAt) j.startedAt = now;
|
|
478
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
479
|
+
}
|
|
480
|
+
export function completeRecommendationJobV2(id) {
|
|
481
|
+
const j = _crjsV2.get(id);
|
|
482
|
+
if (!j) throw new Error(`recommendation job ${id} not found`);
|
|
483
|
+
_crjCheckJ(j.status, RECOMMENDATION_JOB_LIFECYCLE_V2.COMPLETED);
|
|
484
|
+
const now = Date.now();
|
|
485
|
+
j.status = RECOMMENDATION_JOB_LIFECYCLE_V2.COMPLETED;
|
|
486
|
+
j.updatedAt = now;
|
|
487
|
+
if (!j.settledAt) j.settledAt = now;
|
|
488
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
489
|
+
}
|
|
490
|
+
export function failRecommendationJobV2(id, reason) {
|
|
491
|
+
const j = _crjsV2.get(id);
|
|
492
|
+
if (!j) throw new Error(`recommendation job ${id} not found`);
|
|
493
|
+
_crjCheckJ(j.status, RECOMMENDATION_JOB_LIFECYCLE_V2.FAILED);
|
|
494
|
+
const now = Date.now();
|
|
495
|
+
j.status = RECOMMENDATION_JOB_LIFECYCLE_V2.FAILED;
|
|
496
|
+
j.updatedAt = now;
|
|
497
|
+
if (!j.settledAt) j.settledAt = now;
|
|
498
|
+
if (reason) j.metadata.failReason = String(reason);
|
|
499
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
500
|
+
}
|
|
501
|
+
export function cancelRecommendationJobV2(id, reason) {
|
|
502
|
+
const j = _crjsV2.get(id);
|
|
503
|
+
if (!j) throw new Error(`recommendation job ${id} not found`);
|
|
504
|
+
_crjCheckJ(j.status, RECOMMENDATION_JOB_LIFECYCLE_V2.CANCELLED);
|
|
505
|
+
const now = Date.now();
|
|
506
|
+
j.status = RECOMMENDATION_JOB_LIFECYCLE_V2.CANCELLED;
|
|
507
|
+
j.updatedAt = now;
|
|
508
|
+
if (!j.settledAt) j.settledAt = now;
|
|
509
|
+
if (reason) j.metadata.cancelReason = String(reason);
|
|
510
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
511
|
+
}
|
|
512
|
+
export function getRecommendationJobV2(id) {
|
|
513
|
+
const j = _crjsV2.get(id);
|
|
514
|
+
if (!j) return null;
|
|
515
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
516
|
+
}
|
|
517
|
+
export function listRecommendationJobsV2() {
|
|
518
|
+
return [..._crjsV2.values()].map((j) => ({
|
|
519
|
+
...j,
|
|
520
|
+
metadata: { ...j.metadata },
|
|
521
|
+
}));
|
|
522
|
+
}
|
|
302
523
|
|
|
303
|
-
export function autoStaleIdleRecommenderProfilesV2({ now } = {}) {
|
|
304
|
-
|
|
524
|
+
export function autoStaleIdleRecommenderProfilesV2({ now } = {}) {
|
|
525
|
+
const t = now ?? Date.now();
|
|
526
|
+
const flipped = [];
|
|
527
|
+
for (const p of _crpsV2.values())
|
|
528
|
+
if (
|
|
529
|
+
p.status === RECOMMENDER_PROFILE_MATURITY_V2.ACTIVE &&
|
|
530
|
+
t - p.lastTouchedAt >= _crpIdleMs
|
|
531
|
+
) {
|
|
532
|
+
p.status = RECOMMENDER_PROFILE_MATURITY_V2.STALE;
|
|
533
|
+
p.updatedAt = t;
|
|
534
|
+
flipped.push(p.id);
|
|
535
|
+
}
|
|
536
|
+
return { flipped, count: flipped.length };
|
|
537
|
+
}
|
|
538
|
+
export function autoFailStuckRecommendationJobsV2({ now } = {}) {
|
|
539
|
+
const t = now ?? Date.now();
|
|
540
|
+
const flipped = [];
|
|
541
|
+
for (const j of _crjsV2.values())
|
|
542
|
+
if (
|
|
543
|
+
j.status === RECOMMENDATION_JOB_LIFECYCLE_V2.RUNNING &&
|
|
544
|
+
j.startedAt != null &&
|
|
545
|
+
t - j.startedAt >= _crjStuckMs
|
|
546
|
+
) {
|
|
547
|
+
j.status = RECOMMENDATION_JOB_LIFECYCLE_V2.FAILED;
|
|
548
|
+
j.updatedAt = t;
|
|
549
|
+
if (!j.settledAt) j.settledAt = t;
|
|
550
|
+
j.metadata.failReason = "auto-fail-stuck";
|
|
551
|
+
flipped.push(j.id);
|
|
552
|
+
}
|
|
553
|
+
return { flipped, count: flipped.length };
|
|
554
|
+
}
|
|
305
555
|
|
|
306
556
|
export function getContentRecommenderGovStatsV2() {
|
|
307
|
-
const profilesByStatus = {};
|
|
308
|
-
|
|
309
|
-
|
|
557
|
+
const profilesByStatus = {};
|
|
558
|
+
for (const s of Object.values(RECOMMENDER_PROFILE_MATURITY_V2))
|
|
559
|
+
profilesByStatus[s] = 0;
|
|
560
|
+
for (const p of _crpsV2.values()) profilesByStatus[p.status]++;
|
|
561
|
+
const jobsByStatus = {};
|
|
562
|
+
for (const s of Object.values(RECOMMENDATION_JOB_LIFECYCLE_V2))
|
|
563
|
+
jobsByStatus[s] = 0;
|
|
564
|
+
for (const j of _crjsV2.values()) jobsByStatus[j.status]++;
|
|
565
|
+
return {
|
|
566
|
+
totalRecommenderProfilesV2: _crpsV2.size,
|
|
567
|
+
totalRecommendationJobsV2: _crjsV2.size,
|
|
568
|
+
maxActiveRecommenderProfilesPerOwner: _crpMaxActivePerOwner,
|
|
569
|
+
maxPendingRecommendationJobsPerProfile: _crpMaxPendingJobsPerProfile,
|
|
570
|
+
recommenderProfileIdleMs: _crpIdleMs,
|
|
571
|
+
recommendationJobStuckMs: _crjStuckMs,
|
|
572
|
+
profilesByStatus,
|
|
573
|
+
jobsByStatus,
|
|
574
|
+
};
|
|
310
575
|
}
|