@nexus-cortex/core 4.96.1 → 4.98.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/.env.defaults +10 -0
- package/dist/config/effectiveConfig.d.ts.map +1 -1
- package/dist/config/effectiveConfig.js +3 -0
- package/dist/config/effectiveConfig.js.map +1 -1
- package/dist/models/cards/mercury/index.d.ts +1 -0
- package/dist/models/cards/mercury/index.d.ts.map +1 -1
- package/dist/models/cards/mercury/index.js +4 -0
- package/dist/models/cards/mercury/index.js.map +1 -1
- package/dist/models/cards/mercury/mercury-2-5.d.ts +28 -0
- package/dist/models/cards/mercury/mercury-2-5.d.ts.map +1 -0
- package/dist/models/cards/mercury/mercury-2-5.js +37 -0
- package/dist/models/cards/mercury/mercury-2-5.js.map +1 -0
- package/dist/models/registry/ModularModelRegistry.d.ts.map +1 -1
- package/dist/models/registry/ModularModelRegistry.js +2 -1
- package/dist/models/registry/ModularModelRegistry.js.map +1 -1
- package/dist/orchestrator/APIClient.d.ts.map +1 -1
- package/dist/orchestrator/APIClient.js +17 -0
- package/dist/orchestrator/APIClient.js.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.d.ts +16 -0
- package/dist/orchestrator/CortexOrchestrator.d.ts.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.js +74 -5
- package/dist/orchestrator/CortexOrchestrator.js.map +1 -1
- package/dist/orchestrator/dsmlRecovery.d.ts +40 -0
- package/dist/orchestrator/dsmlRecovery.d.ts.map +1 -0
- package/dist/orchestrator/dsmlRecovery.js +106 -0
- package/dist/orchestrator/dsmlRecovery.js.map +1 -0
- package/dist/orchestrator/sliceBlock.d.ts +50 -0
- package/dist/orchestrator/sliceBlock.d.ts.map +1 -0
- package/dist/orchestrator/sliceBlock.js +69 -0
- package/dist/orchestrator/sliceBlock.js.map +1 -0
- package/dist/tools/ToolProfile.d.ts +6 -0
- package/dist/tools/ToolProfile.d.ts.map +1 -1
- package/dist/tools/ToolProfile.js +14 -0
- package/dist/tools/ToolProfile.js.map +1 -1
- package/dist/training/DecisionStore.d.ts +1 -1
- package/dist/training/DecisionStore.d.ts.map +1 -1
- package/dist/training/DecisionStore.js.map +1 -1
- package/package.json +3 -3
|
@@ -35,7 +35,8 @@ import { CacheMetricsAccumulator } from '../session/CacheMetricsAccumulator.js';
|
|
|
35
35
|
import { SubAgentProcessManager, createSubAgentProcessManager } from './SubAgentProcessManager.js';
|
|
36
36
|
// Phase 1: Tool Architecture Refactor - Unified Tool Registry
|
|
37
37
|
import { toolFactory } from '../tools/ToolFactory.js';
|
|
38
|
-
import { resolveToolProfile, resolveToolAnchor, resolveFrameProfile, resolveLiftNudge, resolveLiftPlan, resolveEndTurnResolver, resolveHeadlessDropAskUser, resolveDeferredLoading, isNarrowProfile, isToolAllowedByProfile, applyToolProfile, webToolBlocked, resolveVisionHelperModel, resolveVisionHandoffMax, resolveSliceNudge } from '../tools/ToolProfile.js';
|
|
38
|
+
import { resolveToolProfile, resolveToolAnchor, resolveFrameProfile, resolveLiftNudge, resolveLiftPlan, resolveEndTurnResolver, resolveHeadlessDropAskUser, resolveDeferredLoading, isNarrowProfile, isToolAllowedByProfile, applyToolProfile, webToolBlocked, resolveVisionHelperModel, resolveVisionHandoffMax, resolveSliceNudge, resolveSliceBlock, resolveSliceBlockAt, resolveSliceBlockMax } from '../tools/ToolProfile.js';
|
|
39
|
+
import { sliceReadFile, decideSliceBlock } from './sliceBlock.js';
|
|
39
40
|
import { TurnEvidence, evaluateEndTurnGates, buildMissingEndTurnReminder } from './endTurnGates.js';
|
|
40
41
|
import { resolveOuterToolDeadlineMs } from './outerToolTimeout.js';
|
|
41
42
|
import { resolveTurnDeadlineMs, timeBudgetState, timeBudgetWarnNudge } from './timeBudget.js';
|
|
@@ -1518,6 +1519,7 @@ export class CortexOrchestrator {
|
|
|
1518
1519
|
// Keep executing tools until model returns a text response
|
|
1519
1520
|
let currentAssistantMessage = assistantMessage;
|
|
1520
1521
|
let currentAssistantCanonicalMessage = assistantCanonicalMessage;
|
|
1522
|
+
this.recordDsmlRecovery(currentAssistantCanonicalMessage);
|
|
1521
1523
|
let toolCallIteration = 0;
|
|
1522
1524
|
// Loop control settings — single source of truth via getLoopControlConfig()
|
|
1523
1525
|
const loopDefaults = this.getLoopControlConfig();
|
|
@@ -3635,6 +3637,7 @@ export class CortexOrchestrator {
|
|
|
3635
3637
|
throw new Error('No response message returned from provider');
|
|
3636
3638
|
}
|
|
3637
3639
|
let currentAssistantCanonicalMessage = convertedResponse.messages[0];
|
|
3640
|
+
this.recordDsmlRecovery(currentAssistantCanonicalMessage);
|
|
3638
3641
|
const assistantMessageId = currentAssistantCanonicalMessage.uuid;
|
|
3639
3642
|
const assistantMessage = {
|
|
3640
3643
|
uuid: assistantMessageId,
|
|
@@ -6077,6 +6080,12 @@ export class CortexOrchestrator {
|
|
|
6077
6080
|
results.push(await this.processToolTraining(toolUse, loopBlocked));
|
|
6078
6081
|
continue;
|
|
6079
6082
|
}
|
|
6083
|
+
// CORTEX_SLICE_BLOCK: coercively block re-slicing a static file (force Read) — dark.
|
|
6084
|
+
const sliceBlocked = this.maybeBlockSliceRead(toolUse);
|
|
6085
|
+
if (sliceBlocked) {
|
|
6086
|
+
results.push(await this.processToolTraining(toolUse, sliceBlocked));
|
|
6087
|
+
continue;
|
|
6088
|
+
}
|
|
6080
6089
|
// Context management tools (CORTEX.md generation + two-tier memory)
|
|
6081
6090
|
const contextManagementToolNames = [
|
|
6082
6091
|
'InitCortexContext',
|
|
@@ -6507,6 +6516,10 @@ export class CortexOrchestrator {
|
|
|
6507
6516
|
const loopBlocked = await this.maybeBlockLoopingTool(toolUse);
|
|
6508
6517
|
if (loopBlocked)
|
|
6509
6518
|
return loopBlocked;
|
|
6519
|
+
// CORTEX_SLICE_BLOCK: coercively block re-slicing a static file (force Read) — dark.
|
|
6520
|
+
const sliceBlocked = this.maybeBlockSliceRead(toolUse);
|
|
6521
|
+
if (sliceBlocked)
|
|
6522
|
+
return sliceBlocked;
|
|
6510
6523
|
// Context management tools
|
|
6511
6524
|
const contextManagementToolNames = ['InitCortexContext'];
|
|
6512
6525
|
const isContextManagementTool = contextManagementToolNames.includes(toolUse.name);
|
|
@@ -7251,6 +7264,8 @@ export class CortexOrchestrator {
|
|
|
7251
7264
|
visionHandoffsThisTurn = 0;
|
|
7252
7265
|
/** Per-session bash slice-read counts per file (CORTEX_SLICE_NUDGE). */
|
|
7253
7266
|
sliceReads = new Map();
|
|
7267
|
+
/** Per-session coercive-block counts per file (CORTEX_SLICE_BLOCK — HB-SLICE-BLOCK). */
|
|
7268
|
+
sliceBlockCounts = new Map();
|
|
7254
7269
|
/** Dependencies the shared EndTurn gates need from the orchestrator (endTurnGates.ts). */
|
|
7255
7270
|
gateDeps() {
|
|
7256
7271
|
return {
|
|
@@ -7278,11 +7293,9 @@ export class CortexOrchestrator {
|
|
|
7278
7293
|
applySliceNudge(toolUse, result) {
|
|
7279
7294
|
if (toolUse.name !== 'Bash' || result.is_error || !resolveSliceNudge(process.env))
|
|
7280
7295
|
return;
|
|
7281
|
-
const
|
|
7282
|
-
|
|
7283
|
-
if (!m)
|
|
7296
|
+
const file = sliceReadFile(String(toolUse.input?.command ?? ''));
|
|
7297
|
+
if (!file)
|
|
7284
7298
|
return;
|
|
7285
|
-
const file = m[1];
|
|
7286
7299
|
const n = (this.sliceReads.get(file) ?? 0) + 1;
|
|
7287
7300
|
this.sliceReads.set(file, n);
|
|
7288
7301
|
if (n !== 3)
|
|
@@ -7292,6 +7305,37 @@ export class CortexOrchestrator {
|
|
|
7292
7305
|
}
|
|
7293
7306
|
this.gateDeps().recordEvent('steering_injected', { kind: 'slice_read', file, count: n }, 'Bash');
|
|
7294
7307
|
}
|
|
7308
|
+
/**
|
|
7309
|
+
* CORTEX_SLICE_BLOCK (HB-SLICE-BLOCK) — the coercive escalation of the ignored slice-nudge.
|
|
7310
|
+
* PRE-EXECUTION gate (sibling of maybeBlockLoopingTool): if the model is calling Bash to slice-read
|
|
7311
|
+
* a STATIC/source file it has already sliced >= CORTEX_SLICE_BLOCK_AT times, do NOT run the slice —
|
|
7312
|
+
* return an append-only redirect error steering it to Read (bounded to CORTEX_SLICE_BLOCK_MAX blocks
|
|
7313
|
+
* per file). Append-mostly logs are exempt (legit re-tailing). Dark by default. Evidence: full-sample
|
|
7314
|
+
* mining showed the soft nudge is ignored ~80% of re-tested cases (docs/HB-SLICE-BLOCK-SPEC.md).
|
|
7315
|
+
*/
|
|
7316
|
+
maybeBlockSliceRead(toolUse) {
|
|
7317
|
+
if (toolUse.name !== 'Bash' || !resolveSliceBlock(process.env))
|
|
7318
|
+
return null;
|
|
7319
|
+
const file = sliceReadFile(String(toolUse.input?.command ?? ''));
|
|
7320
|
+
if (!file)
|
|
7321
|
+
return null;
|
|
7322
|
+
const priorSlices = this.sliceReads.get(file) ?? 0;
|
|
7323
|
+
const priorBlocks = this.sliceBlockCounts.get(file) ?? 0;
|
|
7324
|
+
const decision = decideSliceBlock(file, priorSlices, priorBlocks, resolveSliceBlockAt(process.env), resolveSliceBlockMax(process.env));
|
|
7325
|
+
if (decision.action !== 'block')
|
|
7326
|
+
return null;
|
|
7327
|
+
this.sliceBlockCounts.set(file, priorBlocks + 1);
|
|
7328
|
+
const store = this.getDecisionStore();
|
|
7329
|
+
if (store)
|
|
7330
|
+
void store.recordEvent({
|
|
7331
|
+
sessionId: this.currentSessionId ?? 'unknown',
|
|
7332
|
+
kind: 'slice_block', toolName: 'Bash',
|
|
7333
|
+
detail: { file, priorSlices, blockNumber: priorBlocks + 1 },
|
|
7334
|
+
}).catch(() => { });
|
|
7335
|
+
if (this.config.debug)
|
|
7336
|
+
console.log(`[SliceBlock] blocked slice-read of ${file} (${priorSlices} prior slices, block #${priorBlocks + 1})`);
|
|
7337
|
+
return { tool_use_id: toolUse.id, tool_name: toolUse.name, content: decision.message, is_error: true, metadata: { sliceBlock: true, file } };
|
|
7338
|
+
}
|
|
7295
7339
|
async applyVisionHandoffs() {
|
|
7296
7340
|
const queue = this.pendingVisionHandoffs;
|
|
7297
7341
|
this.pendingVisionHandoffs = [];
|
|
@@ -7432,6 +7476,31 @@ export class CortexOrchestrator {
|
|
|
7432
7476
|
}
|
|
7433
7477
|
return this.decisionStore;
|
|
7434
7478
|
}
|
|
7479
|
+
/** HB-DSML-PARSE observability (2026-09-09): if the DeepSeek DSML tool-call recovery fired on this
|
|
7480
|
+
* response (recovered tool_use ids are prefixed `dsml_`), record ONE countable `dsml_recovered`
|
|
7481
|
+
* decision event so the bench data shows how often the leak occurred + that the fix is live.
|
|
7482
|
+
* Observability only — never throws into the turn. */
|
|
7483
|
+
recordDsmlRecovery(msg) {
|
|
7484
|
+
try {
|
|
7485
|
+
const content = Array.isArray(msg?.content) ? msg.content : [];
|
|
7486
|
+
const recovered = content.filter((b) => b?.type === 'tool_use' && typeof b?.toolUse?.id === 'string' && b.toolUse.id.startsWith('dsml_'));
|
|
7487
|
+
if (recovered.length === 0)
|
|
7488
|
+
return;
|
|
7489
|
+
const store = this.getDecisionStore();
|
|
7490
|
+
if (store) {
|
|
7491
|
+
void store
|
|
7492
|
+
.recordEvent({
|
|
7493
|
+
sessionId: this.currentSessionId ?? 'unknown',
|
|
7494
|
+
kind: 'dsml_recovered',
|
|
7495
|
+
detail: { count: recovered.length, tools: recovered.map((b) => b.toolUse?.name) },
|
|
7496
|
+
})
|
|
7497
|
+
.catch(() => { });
|
|
7498
|
+
}
|
|
7499
|
+
if (this.config.debug)
|
|
7500
|
+
console.log(`[HB-DSML-PARSE] dsml_recovered event (count=${recovered.length})`);
|
|
7501
|
+
}
|
|
7502
|
+
catch { /* observability only */ }
|
|
7503
|
+
}
|
|
7435
7504
|
isRecordingEnabled() {
|
|
7436
7505
|
return process.env.CORTEX_RECORD_DECISIONS !== 'false';
|
|
7437
7506
|
}
|