@exellix/graph-engine 6.0.0 → 6.0.2

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.
@@ -367,7 +367,7 @@ export function getNodeNarrixDiscovery(node) {
367
367
  return null;
368
368
  const n = narrix;
369
369
  const web = task.taskConfiguration?.aiTaskProfile?.webScoping;
370
- const enableWebScope = web?.enabled === true;
370
+ const enableWebScope = n.enableWebScope === true || web?.enabled === true;
371
371
  return {
372
372
  nodeId: node.id,
373
373
  enabled: true,
@@ -8,10 +8,8 @@ export declare function mapAiTaskProfileQuestionsToWebScopeQuestions(questions:
8
8
  /**
9
9
  * Returns the resolved outbound `RunTaskRequest.narrix` payload.
10
10
  *
11
- * Authoring contract (5.x): `taskConfiguration.narrix` only carries the discovery fields on
12
- * {@link NarrixPreProcessorConfig} (`datasetId`, `layer`, `narrativeTypeIds`, `questionId`).
13
- * Web-scope fields (`enableWebScope`, `webScopeQuestions`, ...) are produced here from
14
- * `taskConfiguration.aiTaskProfile.webScoping` and merged onto the wire payload — they are not
15
- * authored on `taskConfiguration.narrix`.
11
+ * `enableWebScope` is forwarded from `taskConfiguration.narrix` (default `false`) and may be set to
12
+ * `true` when `taskConfiguration.aiTaskProfile.webScoping` is active. `webScopeQuestions` are derived
13
+ * only from the ai-task profile.
16
14
  */
17
15
  export declare function applyAiTaskProfileWebScopingToNarrix(narrix: NarrixPreProcessorConfig | undefined, aiTaskProfile: AiTaskProfileMetadata | undefined): ResolvedNarrixWirePayload | undefined;
@@ -25,22 +25,19 @@ function webScopingFromProfileIsActive(profile) {
25
25
  /**
26
26
  * Returns the resolved outbound `RunTaskRequest.narrix` payload.
27
27
  *
28
- * Authoring contract (5.x): `taskConfiguration.narrix` only carries the discovery fields on
29
- * {@link NarrixPreProcessorConfig} (`datasetId`, `layer`, `narrativeTypeIds`, `questionId`).
30
- * Web-scope fields (`enableWebScope`, `webScopeQuestions`, ...) are produced here from
31
- * `taskConfiguration.aiTaskProfile.webScoping` and merged onto the wire payload — they are not
32
- * authored on `taskConfiguration.narrix`.
28
+ * `enableWebScope` is forwarded from `taskConfiguration.narrix` (default `false`) and may be set to
29
+ * `true` when `taskConfiguration.aiTaskProfile.webScoping` is active. `webScopeQuestions` are derived
30
+ * only from the ai-task profile.
33
31
  */
34
32
  export function applyAiTaskProfileWebScopingToNarrix(narrix, aiTaskProfile) {
35
- const base = narrix != null ? { ...narrix } : undefined;
36
- if (!webScopingFromProfileIsActive(aiTaskProfile)) {
37
- return base;
33
+ const profileActive = webScopingFromProfileIsActive(aiTaskProfile);
34
+ if (narrix == null && !profileActive) {
35
+ return undefined;
38
36
  }
39
- const mapped = mapAiTaskProfileQuestionsToWebScopeQuestions(aiTaskProfile.webScoping.questions);
40
- const wire = (base ?? {});
41
- return {
42
- ...wire,
43
- enableWebScope: true,
44
- webScopeQuestions: mapped,
45
- };
37
+ const wire = (narrix != null ? { ...narrix } : {});
38
+ wire.enableWebScope = narrix?.enableWebScope === true || profileActive;
39
+ if (profileActive) {
40
+ wire.webScopeQuestions = mapAiTaskProfileQuestionsToWebScopeQuestions(aiTaskProfile.webScoping.questions);
41
+ }
42
+ return wire;
46
43
  }
@@ -1,9 +1,9 @@
1
1
  import type { NarrixPreProcessorConfig, ResolvedNarrixWirePayload } from '../types/narrix.js';
2
2
  import type { AiTaskProfileMetadata } from '../types/aiTaskProfile.js';
3
3
  /**
4
- * Resolves outbound `RunTaskRequest.narrix`: starts from node taskConfiguration (authoring shape, no web fields),
5
- * shallow-merges graph-level `variables.narrix` discovery fields, then derives web-scope fields from
6
- * `taskConfiguration.aiTaskProfile.webScoping` via {@link applyAiTaskProfileWebScopingToNarrix}.
4
+ * Resolves outbound `RunTaskRequest.narrix`: starts from node `taskConfiguration.narrix`,
5
+ * shallow-merges graph-level `variables.narrix`, then applies `enableWebScope` / `webScopeQuestions`
6
+ * via {@link applyAiTaskProfileWebScopingToNarrix}.
7
7
  *
8
8
  * Shared by {@link ExellixGraphRuntime}.
9
9
  */
@@ -1,8 +1,8 @@
1
1
  import { applyAiTaskProfileWebScopingToNarrix } from './applyAiTaskProfileWebScopingToNarrix.js';
2
2
  /**
3
- * Resolves outbound `RunTaskRequest.narrix`: starts from node taskConfiguration (authoring shape, no web fields),
4
- * shallow-merges graph-level `variables.narrix` discovery fields, then derives web-scope fields from
5
- * `taskConfiguration.aiTaskProfile.webScoping` via {@link applyAiTaskProfileWebScopingToNarrix}.
3
+ * Resolves outbound `RunTaskRequest.narrix`: starts from node `taskConfiguration.narrix`,
4
+ * shallow-merges graph-level `variables.narrix`, then applies `enableWebScope` / `webScopeQuestions`
5
+ * via {@link applyAiTaskProfileWebScopingToNarrix}.
6
6
  *
7
7
  * Shared by {@link ExellixGraphRuntime}.
8
8
  */
@@ -95,9 +95,8 @@ const LEGACY_METADATA_TO_TASK_CONFIGURATION = {
95
95
  executionMemory: 'runtime.executionMemory',
96
96
  outputsMemory: 'runtime.outputsMemory',
97
97
  };
98
- /** Web-scope keys are not allowed under `taskConfiguration.narrix` (use `taskConfiguration.aiTaskProfile.webScoping`). */
98
+ /** Web-scope keys are not allowed under `taskConfiguration.narrix` except `enableWebScope` (use `taskConfiguration.aiTaskProfile.webScoping` for questions). */
99
99
  const FORBIDDEN_NARRIX_WEB_KEYS = [
100
- 'enableWebScope',
101
100
  'forceWebScope',
102
101
  'webScopeQuestions',
103
102
  'webScoping',
@@ -466,6 +465,11 @@ export function assertCanonicalTaskNode(node, context) {
466
465
  }
467
466
  const narrixTc = tc && isPlainObject(tc.narrix) ? tc.narrix : undefined;
468
467
  if (narrixTc) {
468
+ if ('enableWebScope' in narrixTc &&
469
+ narrixTc.enableWebScope != null &&
470
+ typeof narrixTc.enableWebScope !== 'boolean') {
471
+ throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_TASK_NODE, `Task node "${String(node.id)}": taskConfiguration.narrix.enableWebScope must be a boolean when present.`, { jobId: context?.jobId, graphId: context?.graphId, nodeId: String(node.id), narrixWebKey: 'enableWebScope' });
472
+ }
469
473
  for (const k of FORBIDDEN_NARRIX_WEB_KEYS) {
470
474
  if (k in narrixTc) {
471
475
  throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_TASK_NODE, `Task node "${String(node.id)}": taskConfiguration.narrix.${k} is forbidden — author web scope under taskConfiguration.aiTaskProfile.webScoping.`, { jobId: context?.jobId, graphId: context?.graphId, nodeId: String(node.id), narrixWebKey: k });
@@ -3,8 +3,7 @@ import type { RunTaskRequest } from '@exellix/ai-tasks';
3
3
  type AITasksNarrixPreProcessorConfig = NonNullable<RunTaskRequest['narrix']>;
4
4
  /**
5
5
  * Graph-engine wire shape for the resolved `RunTaskRequest.narrix` payload after merging
6
- * `taskConfiguration.aiTaskProfile.webScoping` into `taskConfiguration.narrix`. Used internally; authors do
7
- * **not** set web-scope fields on `taskConfiguration.narrix`.
6
+ * `taskConfiguration.narrix` with graph variables and optional `taskConfiguration.aiTaskProfile.webScoping`.
8
7
  */
9
8
  export type ResolvedNarrixWirePayload = AITasksNarrixPreProcessorConfig;
10
9
  /** One web-scope question on the resolved narrix wire payload; produced from `aiTaskProfile.webScoping.questions`. */
@@ -14,12 +13,10 @@ export type WebScopeQuestion = {
14
13
  purpose?: string;
15
14
  };
16
15
  /**
17
- * Authoring shape for `taskConfiguration.narrix` on a graph task node — discovery only.
16
+ * Authoring shape for `taskConfiguration.narrix` on a graph task node.
18
17
  *
19
- * 5.x removed every web-scope key from this type. Authors set web intent under
20
- * `taskConfiguration.aiTaskProfile.webScoping` (`enabled`, `questions: string[]`); graph-engine
21
- * fills the corresponding fields on the resolved `RunTaskRequest.narrix` automatically,
22
- * and `assertCanonicalGraphDocument` rejects web-scope keys here at load time.
18
+ * Discovery fields plus `enableWebScope` (forwarded to `RunTaskRequest.narrix.enableWebScope`).
19
+ * Question packs for web scoping may also be supplied via `taskConfiguration.aiTaskProfile.webScoping`.
23
20
  */
24
21
  export type NarrixPreProcessorConfig = {
25
22
  /** Which pack and entity type the engine runs (e.g. `"network.vuln.instances"`). */
@@ -33,6 +30,15 @@ export type NarrixPreProcessorConfig = {
33
30
  narrativeTypeIds?: string[];
34
31
  /** Framework question this node answers (e.g. q0, q1, q2, q3, q5, q6). */
35
32
  questionId?: string;
33
+ /** When true, ai-tasks runs `@exellix/narrix-web-scoper` after CNI and writes `executionMemory.webContext`. */
34
+ enableWebScope?: boolean;
35
+ /**
36
+ * When true with `enableWebScope`, skip internal web-scoper if `executionMemory.webContextMarkdown` is already set.
37
+ * See `@exellix/ai-tasks` `NarrixPreProcessorConfig.skipWebScopeWhenExternalWebMarkdownPresent`.
38
+ */
39
+ skipWebScopeWhenExternalWebMarkdownPresent?: boolean;
40
+ /** Execution memory key for the Narrix attachment (default `_narrix` in ai-tasks). */
41
+ attachToField?: string;
36
42
  };
37
43
  /**
38
44
  * Context shape passed to NARRIX graph task handlers (matches ai-tasks LocalTaskContext).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exellix/graph-engine",
3
- "version": "6.0.0",
3
+ "version": "6.0.2",
4
4
  "type": "module",
5
5
  "description": "Graph executor SDK",
6
6
  "main": "dist/src/index.js",
@@ -48,7 +48,7 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@exellix/ai-tasks": "^7.8.1",
51
+ "@exellix/ai-tasks": "^7.8.2",
52
52
  "@x12i/activix": "^7.1.0",
53
53
  "@x12i/catalox": "^5.1.1",
54
54
  "@x12i/env": "^4.0.1",