@exellix/graph-composer 2.0.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.example +66 -0
- package/LICENSE +21 -0
- package/README.md +329 -0
- package/dist/aiTaskProfile.d.ts +66 -0
- package/dist/aiTaskProfile.d.ts.map +1 -0
- package/dist/aiTaskProfile.js +179 -0
- package/dist/canonicalGraphDocument.d.ts +8 -0
- package/dist/canonicalGraphDocument.d.ts.map +1 -0
- package/dist/canonicalGraphDocument.js +344 -0
- package/dist/canonicalGraphWarnings.d.ts +6 -0
- package/dist/canonicalGraphWarnings.d.ts.map +1 -0
- package/dist/canonicalGraphWarnings.js +140 -0
- package/dist/catalogMatchAssist.d.ts +20 -0
- package/dist/catalogMatchAssist.d.ts.map +1 -0
- package/dist/catalogMatchAssist.js +203 -0
- package/dist/cataloxCatalogBridge.d.ts +103 -0
- package/dist/cataloxCatalogBridge.d.ts.map +1 -0
- package/dist/cataloxCatalogBridge.js +222 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +43 -0
- package/dist/composeInstructions.d.ts +11 -0
- package/dist/composeInstructions.d.ts.map +1 -0
- package/dist/composeInstructions.js +39 -0
- package/dist/defaultUtilitySkills.d.ts +4 -0
- package/dist/defaultUtilitySkills.d.ts.map +1 -0
- package/dist/defaultUtilitySkills.js +5 -0
- package/dist/exampleGeneration.d.ts +15 -0
- package/dist/exampleGeneration.d.ts.map +1 -0
- package/dist/exampleGeneration.js +72 -0
- package/dist/exampleInputs.d.ts +12 -0
- package/dist/exampleInputs.d.ts.map +1 -0
- package/dist/exampleInputs.js +181 -0
- package/dist/graphComposerActions.d.ts +22 -0
- package/dist/graphComposerActions.d.ts.map +1 -0
- package/dist/graphComposerActions.js +168 -0
- package/dist/graphComposerAgent.d.ts +26 -0
- package/dist/graphComposerAgent.d.ts.map +1 -0
- package/dist/graphComposerAgent.js +175 -0
- package/dist/graphComposerOutputValidation.d.ts +23 -0
- package/dist/graphComposerOutputValidation.d.ts.map +1 -0
- package/dist/graphComposerOutputValidation.js +709 -0
- package/dist/graphConceptPatchMerge.d.ts +10 -0
- package/dist/graphConceptPatchMerge.d.ts.map +1 -0
- package/dist/graphConceptPatchMerge.js +40 -0
- package/dist/graphEngineBridge.d.ts +7 -0
- package/dist/graphEngineBridge.d.ts.map +1 -0
- package/dist/graphEngineBridge.js +5 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/openRouterConnectTimeout.d.ts +3 -0
- package/dist/openRouterConnectTimeout.d.ts.map +1 -0
- package/dist/openRouterConnectTimeout.js +48 -0
- package/dist/packDir.d.ts +7 -0
- package/dist/packDir.d.ts.map +1 -0
- package/dist/packDir.js +23 -0
- package/dist/parseGraphConceptStory.d.ts +21 -0
- package/dist/parseGraphConceptStory.d.ts.map +1 -0
- package/dist/parseGraphConceptStory.js +105 -0
- package/dist/redactForLog.d.ts +2 -0
- package/dist/redactForLog.d.ts.map +1 -0
- package/dist/redactForLog.js +37 -0
- package/dist/runGraphComposer.d.ts +54 -0
- package/dist/runGraphComposer.d.ts.map +1 -0
- package/dist/runGraphComposer.js +444 -0
- package/dist/scopingCatalogHostTypes.d.ts +28 -0
- package/dist/scopingCatalogHostTypes.d.ts.map +1 -0
- package/dist/scopingCatalogHostTypes.js +6 -0
- package/dist/scopingNeedMatchAssist.d.ts +14 -0
- package/dist/scopingNeedMatchAssist.d.ts.map +1 -0
- package/dist/scopingNeedMatchAssist.js +58 -0
- package/dist/taskNodeTaskVariable.d.ts +44 -0
- package/dist/taskNodeTaskVariable.d.ts.map +1 -0
- package/dist/taskNodeTaskVariable.js +347 -0
- package/dist/types.d.ts +174 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/examples/network-vuln-subnet-triage.v2.json +389 -0
- package/functions/graph-composer/meta.json +607 -0
- package/functions/graph-composer/prompts/README.md +46 -0
- package/functions/graph-composer/prompts/action-create.md +51 -0
- package/functions/graph-composer/prompts/action-explain.md +26 -0
- package/functions/graph-composer/prompts/action-modify.md +32 -0
- package/functions/graph-composer/prompts/action-review-concept.md +97 -0
- package/functions/graph-composer/prompts/action-suggest-catalog-creations.md +31 -0
- package/functions/graph-composer/prompts/action-suggest-catalog-resolution.md +42 -0
- package/functions/graph-composer/prompts/action-suggest-concept-objective.md +38 -0
- package/functions/graph-composer/prompts/action-suggest-scoping-map-creation.md +31 -0
- package/functions/graph-composer/prompts/action-suggest-scoping-need-match.md +25 -0
- package/functions/graph-composer/prompts/default-utility-skills.json +22 -0
- package/functions/graph-composer/prompts/judge-rules.md +30 -0
- package/functions/graph-composer/prompts/orchestrator-system.md +21 -0
- package/functions/graph-composer/prompts/shared/graph-format.md +124 -0
- package/functions/graph-composer/prompts/shared/request-context.md +12 -0
- package/functions/graph-composer/prompts/shared/skill-selection.md +6 -0
- package/functions/graph-composer/prompts/shared/structural-validation.md +19 -0
- package/functions/graph-composer/prompts/skill-catalog-ai-header.md +3 -0
- package/functions/graph-composer/prompts/skill-catalog-utility-header.md +3 -0
- package/functions/graph-composer/prompts/skill-mode-extensible.md +7 -0
- package/functions/graph-composer/prompts/skill-mode-locked.md +7 -0
- package/functions/graph-composer/test-cases.json +52 -0
- package/package.json +86 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SkillDescriptor } from "./types.js";
|
|
2
|
+
/** Loaded from `functions/graph-composer/prompts/default-utility-skills.json` when `utilitySkills` is omitted. */
|
|
3
|
+
export declare const DEFAULT_UTILITY_SKILLS: SkillDescriptor[];
|
|
4
|
+
//# sourceMappingURL=defaultUtilitySkills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultUtilitySkills.d.ts","sourceRoot":"","sources":["../src/defaultUtilitySkills.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,kHAAkH;AAClH,eAAO,MAAM,sBAAsB,EAAE,eAAe,EAK9B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { graphComposerPackRoot } from "./packDir.js";
|
|
4
|
+
/** Loaded from `functions/graph-composer/prompts/default-utility-skills.json` when `utilitySkills` is omitted. */
|
|
5
|
+
export const DEFAULT_UTILITY_SKILLS = JSON.parse(readFileSync(path.join(graphComposerPackRoot(), "prompts", "default-utility-skills.json"), "utf-8"));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { generateContentExample, generateJsonExample, generateMdExample, type ExampleGenLlmOptions, type GenerateContentExampleParams, type GenerateContentExampleResult, type GenerateJsonExampleResult, type GenerateMdExampleParams, type GenerateMdExampleResult } from "@x12i/funcx/functions";
|
|
2
|
+
export type GenerateGraphJsonInputExampleParams = ExampleGenLlmOptions & {
|
|
3
|
+
/** JSON Schema for the input payload expected by the graph. */
|
|
4
|
+
jsonSchema: unknown;
|
|
5
|
+
/** Optional worox graph; metadata is summarized into guidance for the generator. */
|
|
6
|
+
existingGraph?: object;
|
|
7
|
+
/** Domain and product hints. Appended after graph-derived guidance. */
|
|
8
|
+
guidance?: string[];
|
|
9
|
+
/** Optional known-good or stylistic examples. */
|
|
10
|
+
examples?: unknown[];
|
|
11
|
+
};
|
|
12
|
+
export declare function buildGraphInputExampleGuidance(existingGraph: object | undefined, guidance?: string[]): string[];
|
|
13
|
+
export declare function generateGraphJsonInputExample(params: GenerateGraphJsonInputExampleParams): Promise<GenerateJsonExampleResult>;
|
|
14
|
+
export { generateContentExample, generateJsonExample, generateMdExample, type GenerateContentExampleParams, type GenerateContentExampleResult, type GenerateJsonExampleResult, type GenerateMdExampleParams, type GenerateMdExampleResult, };
|
|
15
|
+
//# sourceMappingURL=exampleGeneration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exampleGeneration.d.ts","sourceRoot":"","sources":["../src/exampleGeneration.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAI/B,MAAM,MAAM,mCAAmC,GAAG,oBAAoB,GAAG;IACvE,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;IACpB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB,CAAC;AA0DF,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,QAAQ,GAAE,MAAM,EAAO,GACtB,MAAM,EAAE,CASV;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,mCAAmC,GAC1C,OAAO,CAAC,yBAAyB,CAAC,CAcpC;AAED,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { generateContentExample, generateJsonExample, generateMdExample, } from "@x12i/funcx/functions";
|
|
2
|
+
function asObject(v) {
|
|
3
|
+
return v !== null && typeof v === "object" && !Array.isArray(v)
|
|
4
|
+
? v
|
|
5
|
+
: undefined;
|
|
6
|
+
}
|
|
7
|
+
function pickString(o, key) {
|
|
8
|
+
const v = o?.[key];
|
|
9
|
+
return typeof v === "string" && v.trim().length > 0 ? v.trim() : undefined;
|
|
10
|
+
}
|
|
11
|
+
function truncate(s, max = 320) {
|
|
12
|
+
return s.length > max ? `${s.slice(0, max - 3)}...` : s;
|
|
13
|
+
}
|
|
14
|
+
function graphConceptGuidance(existingGraph) {
|
|
15
|
+
if (!existingGraph)
|
|
16
|
+
return [];
|
|
17
|
+
const graph = asObject(existingGraph);
|
|
18
|
+
const metadata = asObject(graph?.metadata);
|
|
19
|
+
const concept = asObject(metadata?.graphConcept);
|
|
20
|
+
const hints = [];
|
|
21
|
+
const graphId = pickString(graph, "id");
|
|
22
|
+
if (graphId)
|
|
23
|
+
hints.push(`Graph id: ${graphId}.`);
|
|
24
|
+
for (const [label, key] of [
|
|
25
|
+
["Primary intent", "primaryIntentStatement"],
|
|
26
|
+
["Business objective", "businessObjective"],
|
|
27
|
+
["Expected input", "expectedInput"],
|
|
28
|
+
["Output description", "outputDescription"],
|
|
29
|
+
["Persistence notes", "persistenceNotes"],
|
|
30
|
+
]) {
|
|
31
|
+
const value = pickString(concept, key);
|
|
32
|
+
if (value)
|
|
33
|
+
hints.push(`${label}: ${truncate(value)}.`);
|
|
34
|
+
}
|
|
35
|
+
const coreTasks = concept?.coreTasks;
|
|
36
|
+
if (Array.isArray(coreTasks)) {
|
|
37
|
+
const taskHints = coreTasks
|
|
38
|
+
.slice(0, 8)
|
|
39
|
+
.map((task, idx) => {
|
|
40
|
+
const t = asObject(task);
|
|
41
|
+
const statement = pickString(t, "statement");
|
|
42
|
+
const details = pickString(t, "details");
|
|
43
|
+
const body = [statement, details].filter(Boolean).join(" - ");
|
|
44
|
+
return body ? `${idx + 1}. ${truncate(body, 220)}` : undefined;
|
|
45
|
+
})
|
|
46
|
+
.filter((x) => x !== undefined);
|
|
47
|
+
if (taskHints.length > 0) {
|
|
48
|
+
hints.push(`Core tasks: ${taskHints.join(" | ")}.`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return hints;
|
|
52
|
+
}
|
|
53
|
+
export function buildGraphInputExampleGuidance(existingGraph, guidance = []) {
|
|
54
|
+
return [
|
|
55
|
+
"Generate one realistic example input payload for running this specific worox graph.",
|
|
56
|
+
"The example must satisfy the provided JSON Schema.",
|
|
57
|
+
"Use fake but plausible values only; do not create real secrets, API keys, tokens, passwords, or private identifiers.",
|
|
58
|
+
"Prefer a compact happy-path example unless the caller guidance asks for an edge case.",
|
|
59
|
+
...graphConceptGuidance(existingGraph),
|
|
60
|
+
...guidance,
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
export async function generateGraphJsonInputExample(params) {
|
|
64
|
+
const { jsonSchema, existingGraph, guidance, examples, ...llmOptions } = params;
|
|
65
|
+
return generateJsonExample({
|
|
66
|
+
jsonSchema,
|
|
67
|
+
guidance: buildGraphInputExampleGuidance(existingGraph, guidance),
|
|
68
|
+
examples,
|
|
69
|
+
...llmOptions,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export { generateContentExample, generateJsonExample, generateMdExample, };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GraphComposerInput } from "./types.js";
|
|
2
|
+
export declare function loadExampleGraph(filename: string): Record<string, unknown>;
|
|
3
|
+
/** Skill catalog matching nodes in `network-vuln-subnet-triage.v2.json` (locked explain). */
|
|
4
|
+
export declare function inputExplainNetworkVulnSubnet(): GraphComposerInput;
|
|
5
|
+
/** Same graph as `inputExplainNetworkVulnSubnet`, for `suggestConceptObjective` (locked catalog). */
|
|
6
|
+
export declare function inputSuggestConceptObjectiveNetworkVulnSubnet(): GraphComposerInput;
|
|
7
|
+
/**
|
|
8
|
+
* `reviewConcept` live smoke: real graph plus `metadata.graphConcept.coreTasks` (length 2) and
|
|
9
|
+
* `metadata.narrix` on a node — prompts should yield deep requirements or `requirementOptions` / IO findings.
|
|
10
|
+
*/
|
|
11
|
+
export declare function inputReviewConceptIoSmoke(): GraphComposerInput;
|
|
12
|
+
//# sourceMappingURL=exampleInputs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exampleInputs.d.ts","sourceRoot":"","sources":["../src/exampleInputs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIrD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAO1E;AAED,6FAA6F;AAC7F,wBAAgB,6BAA6B,IAAI,kBAAkB,CA4ClE;AAED,qGAAqG;AACrG,wBAAgB,6CAA6C,IAAI,kBAAkB,CA+ClF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,kBAAkB,CAsF9D"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const repoRoot = path.join(fileURLToPath(new URL("..", import.meta.url)));
|
|
5
|
+
export function loadExampleGraph(filename) {
|
|
6
|
+
const p = path.join(repoRoot, "examples", filename);
|
|
7
|
+
const data = JSON.parse(readFileSync(p, "utf-8"));
|
|
8
|
+
if (data === null || typeof data !== "object") {
|
|
9
|
+
throw new Error(`Example graph ${filename} must be a JSON object`);
|
|
10
|
+
}
|
|
11
|
+
return data;
|
|
12
|
+
}
|
|
13
|
+
/** Skill catalog matching nodes in `network-vuln-subnet-triage.v2.json` (locked explain). */
|
|
14
|
+
export function inputExplainNetworkVulnSubnet() {
|
|
15
|
+
const existingGraph = loadExampleGraph("network-vuln-subnet-triage.v2.json");
|
|
16
|
+
return {
|
|
17
|
+
intent: {
|
|
18
|
+
action: "explain",
|
|
19
|
+
description: "Explain this production worox graph end-to-end: parallel readers, deterministic branches (CVSS tier, zone routing), LLM step role, and how the finalizer aggregates outputs. Note conditional edges if any.",
|
|
20
|
+
},
|
|
21
|
+
existingGraph,
|
|
22
|
+
skillMode: "locked",
|
|
23
|
+
aiSkills: [
|
|
24
|
+
{
|
|
25
|
+
skillKey: "professional-answer",
|
|
26
|
+
description: "LLM-backed structured analysis for security/subnet triage (used when rules route to main synthesis path)",
|
|
27
|
+
isLocal: false,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
utilitySkills: [
|
|
31
|
+
{
|
|
32
|
+
skillKey: "scoped-data-reader",
|
|
33
|
+
description: "Read scoped documents (subnet inventory, risk summary, topology/exposure) from x-scoped-data",
|
|
34
|
+
isLocal: true,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
skillKey: "deterministic-rule",
|
|
38
|
+
description: "Evaluate ordered rules for zone classification, CVSS-based tier skip, and branch routing without LLM",
|
|
39
|
+
isLocal: true,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
skillKey: "scoped-answer-assembler",
|
|
43
|
+
description: "Assemble final subnet triage answer payload from upstream node outputs",
|
|
44
|
+
isLocal: true,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
skillKey: "scoped-answer-writer",
|
|
48
|
+
description: "Persist triage verdicts / inferences to scoped store (e.g. subnet-triage-verdicts scope map)",
|
|
49
|
+
isLocal: true,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Same graph as `inputExplainNetworkVulnSubnet`, for `suggestConceptObjective` (locked catalog). */
|
|
55
|
+
export function inputSuggestConceptObjectiveNetworkVulnSubnet() {
|
|
56
|
+
const existingGraph = loadExampleGraph("network-vuln-subnet-triage.v2.json");
|
|
57
|
+
return {
|
|
58
|
+
intent: {
|
|
59
|
+
action: "suggestConceptObjective",
|
|
60
|
+
description: "Propose graph-level primary intent and objective text for product stakeholders, synthesized from the full pipeline (readers, rules, LLM path, finalizer).",
|
|
61
|
+
},
|
|
62
|
+
existingGraph,
|
|
63
|
+
analysisContext: {
|
|
64
|
+
note: "Stub: real consumers pass full analyzer output (execution order, IO, issues, layers).",
|
|
65
|
+
},
|
|
66
|
+
skillMode: "locked",
|
|
67
|
+
aiSkills: [
|
|
68
|
+
{
|
|
69
|
+
skillKey: "professional-answer",
|
|
70
|
+
description: "LLM-backed structured analysis for security/subnet triage (used when rules route to main synthesis path)",
|
|
71
|
+
isLocal: false,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
utilitySkills: [
|
|
75
|
+
{
|
|
76
|
+
skillKey: "scoped-data-reader",
|
|
77
|
+
description: "Read scoped documents (subnet inventory, risk summary, topology/exposure) from x-scoped-data",
|
|
78
|
+
isLocal: true,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
skillKey: "deterministic-rule",
|
|
82
|
+
description: "Evaluate ordered rules for zone classification, CVSS-based tier skip, and branch routing without LLM",
|
|
83
|
+
isLocal: true,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
skillKey: "scoped-answer-assembler",
|
|
87
|
+
description: "Assemble final subnet triage answer payload from upstream node outputs",
|
|
88
|
+
isLocal: true,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
skillKey: "scoped-answer-writer",
|
|
92
|
+
description: "Persist triage verdicts / inferences to scoped store (e.g. subnet-triage-verdicts scope map)",
|
|
93
|
+
isLocal: true,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* `reviewConcept` live smoke: real graph plus `metadata.graphConcept.coreTasks` (length 2) and
|
|
100
|
+
* `metadata.narrix` on a node — prompts should yield deep requirements or `requirementOptions` / IO findings.
|
|
101
|
+
*/
|
|
102
|
+
export function inputReviewConceptIoSmoke() {
|
|
103
|
+
const base = loadExampleGraph("network-vuln-subnet-triage.v2.json");
|
|
104
|
+
const g = JSON.parse(JSON.stringify(base));
|
|
105
|
+
const prevMeta = g.metadata !== null && typeof g.metadata === "object" && !Array.isArray(g.metadata)
|
|
106
|
+
? g.metadata
|
|
107
|
+
: {};
|
|
108
|
+
g.metadata = {
|
|
109
|
+
...prevMeta,
|
|
110
|
+
graphConcept: {
|
|
111
|
+
coreTasks: [
|
|
112
|
+
{
|
|
113
|
+
taskType: "question",
|
|
114
|
+
statement: "Load subnet and scoped context",
|
|
115
|
+
details: "",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
taskType: "question",
|
|
119
|
+
statement: "Triage and persist verdicts",
|
|
120
|
+
details: "",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
const nodes = g.nodes;
|
|
126
|
+
if (Array.isArray(nodes) && nodes.length > 0) {
|
|
127
|
+
const n0 = nodes[0];
|
|
128
|
+
if (n0 !== null && typeof n0 === "object" && !Array.isArray(n0)) {
|
|
129
|
+
const node = n0;
|
|
130
|
+
const nm = node.metadata !== null &&
|
|
131
|
+
typeof node.metadata === "object" &&
|
|
132
|
+
!Array.isArray(node.metadata)
|
|
133
|
+
? node.metadata
|
|
134
|
+
: {};
|
|
135
|
+
node.metadata = {
|
|
136
|
+
...nm,
|
|
137
|
+
narrix: {
|
|
138
|
+
datasetId: "network.subnets",
|
|
139
|
+
narrativeTypeIds: ["nt-discovery"],
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
intent: {
|
|
146
|
+
action: "reviewConcept",
|
|
147
|
+
description: "Review concept coherence. Populate requirements (narrix, memoryIO, catalogBinding) from the graph; use requirementOptions when ambiguous.",
|
|
148
|
+
},
|
|
149
|
+
existingGraph: g,
|
|
150
|
+
skillMode: "locked",
|
|
151
|
+
aiSkills: [
|
|
152
|
+
{
|
|
153
|
+
skillKey: "professional-answer",
|
|
154
|
+
description: "LLM-backed structured analysis for security/subnet triage (used when rules route to main synthesis path)",
|
|
155
|
+
isLocal: false,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
utilitySkills: [
|
|
159
|
+
{
|
|
160
|
+
skillKey: "scoped-data-reader",
|
|
161
|
+
description: "Read scoped documents (subnet inventory, risk summary, topology/exposure) from x-scoped-data",
|
|
162
|
+
isLocal: true,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
skillKey: "deterministic-rule",
|
|
166
|
+
description: "Evaluate ordered rules for zone classification, CVSS-based tier skip, and branch routing without LLM",
|
|
167
|
+
isLocal: true,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
skillKey: "scoped-answer-assembler",
|
|
171
|
+
description: "Assemble final subnet triage answer payload from upstream node outputs",
|
|
172
|
+
isLocal: true,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
skillKey: "scoped-answer-writer",
|
|
176
|
+
description: "Persist triage verdicts / inferences to scoped store (e.g. subnet-triage-verdicts scope map)",
|
|
177
|
+
isLocal: true,
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GraphComposerIntent } from "./types.js";
|
|
2
|
+
import { type OutputValidator } from "./graphComposerOutputValidation.js";
|
|
3
|
+
export type GraphComposerAction = GraphComposerIntent["action"];
|
|
4
|
+
export type GraphComposerActionDefinition = {
|
|
5
|
+
readonly action: GraphComposerAction;
|
|
6
|
+
/** File under `prompts/` (e.g. `action-create.md`). */
|
|
7
|
+
readonly promptFile: string;
|
|
8
|
+
/** More `prompts/` paths, joined before `promptFile`. */
|
|
9
|
+
readonly sharedIncludes: readonly string[];
|
|
10
|
+
readonly requiresExistingGraph: boolean;
|
|
11
|
+
/** Stable tool id for orchestrator (snake_case). */
|
|
12
|
+
readonly toolName: string;
|
|
13
|
+
readonly toolDescription: string;
|
|
14
|
+
readonly validateOutput: OutputValidator;
|
|
15
|
+
};
|
|
16
|
+
export declare const GRAPH_COMPOSER_ACTION_REGISTRY: readonly GraphComposerActionDefinition[];
|
|
17
|
+
export declare function getActionDefinition(action: string): GraphComposerActionDefinition;
|
|
18
|
+
export declare function getActionDefinitionByToolName(toolName: string): GraphComposerActionDefinition | undefined;
|
|
19
|
+
/** Ordered prompt paths that must exist on disk (for verify-local). */
|
|
20
|
+
export declare function requiredPromptPathsFromRegistry(): string[];
|
|
21
|
+
export declare function loadWorkerBaseMarkdown(action: GraphComposerAction): string;
|
|
22
|
+
//# sourceMappingURL=graphComposerActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphComposerActions.d.ts","sourceRoot":"","sources":["../src/graphComposerActions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,KAAK,eAAe,EASrB,MAAM,oCAAoC,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAEhE,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC;CAC1C,CAAC;AAaF,eAAO,MAAM,8BAA8B,EAAE,SAAS,6BAA6B,EAkIvE,CAAC;AAYb,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GACb,6BAA6B,CAQ/B;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,GACf,6BAA6B,GAAG,SAAS,CAE3C;AAED,uEAAuE;AACvE,wBAAgB,+BAA+B,IAAI,MAAM,EAAE,CAQ1D;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAS1E"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { graphComposerPackRoot } from "./packDir.js";
|
|
4
|
+
import { validateCreateModifyOutput, validateExplainOutput, validateSuggestCatalogCreationsOutput, validateSuggestCatalogResolutionOutput, validateSuggestConceptOutput, validateSuggestScopingMapCreationOutput, validateSuggestScopingNeedMatchOutput, validateReviewConceptOutput, } from "./graphComposerOutputValidation.js";
|
|
5
|
+
function readPromptRelative(rel) {
|
|
6
|
+
const root = graphComposerPackRoot();
|
|
7
|
+
const p = path.join(root, "prompts", rel);
|
|
8
|
+
if (!existsSync(p)) {
|
|
9
|
+
throw new Error(`Missing pack prompt file: ${p}`);
|
|
10
|
+
}
|
|
11
|
+
return readFileSync(p, "utf-8");
|
|
12
|
+
}
|
|
13
|
+
const workerBaseMarkdownCache = new Map();
|
|
14
|
+
export const GRAPH_COMPOSER_ACTION_REGISTRY = [
|
|
15
|
+
{
|
|
16
|
+
action: "create",
|
|
17
|
+
promptFile: "action-create.md",
|
|
18
|
+
sharedIncludes: [
|
|
19
|
+
"shared/request-context.md",
|
|
20
|
+
"shared/graph-format.md",
|
|
21
|
+
"shared/skill-selection.md",
|
|
22
|
+
"shared/structural-validation.md",
|
|
23
|
+
],
|
|
24
|
+
requiresExistingGraph: false,
|
|
25
|
+
toolName: "graph_create",
|
|
26
|
+
toolDescription: "Build a new worox-graph from intentDescription and constraints. Returns full graph + changelog.",
|
|
27
|
+
validateOutput: (out, ctx) => {
|
|
28
|
+
validateCreateModifyOutput(out, ctx);
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
action: "modify",
|
|
33
|
+
promptFile: "action-modify.md",
|
|
34
|
+
sharedIncludes: [
|
|
35
|
+
"shared/request-context.md",
|
|
36
|
+
"shared/graph-format.md",
|
|
37
|
+
"shared/skill-selection.md",
|
|
38
|
+
"shared/structural-validation.md",
|
|
39
|
+
],
|
|
40
|
+
requiresExistingGraph: true,
|
|
41
|
+
toolName: "graph_modify",
|
|
42
|
+
toolDescription: "Patch an existing worox-graph per intentDescription. Preserves unaffected structure. Returns full graph + changelog.",
|
|
43
|
+
validateOutput: (out, ctx) => {
|
|
44
|
+
validateCreateModifyOutput(out, ctx);
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
action: "explain",
|
|
49
|
+
promptFile: "action-explain.md",
|
|
50
|
+
sharedIncludes: [
|
|
51
|
+
"shared/request-context.md",
|
|
52
|
+
"shared/graph-format.md",
|
|
53
|
+
"shared/skill-selection.md",
|
|
54
|
+
],
|
|
55
|
+
requiresExistingGraph: true,
|
|
56
|
+
toolName: "graph_explain",
|
|
57
|
+
toolDescription: "Explain existingGraph for engineers/operators: summary, execution order, node descriptions, data flow, conditional paths. No graph JSON returned.",
|
|
58
|
+
validateOutput: validateExplainOutput,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
action: "suggestConceptObjective",
|
|
62
|
+
promptFile: "action-suggest-concept-objective.md",
|
|
63
|
+
sharedIncludes: ["shared/request-context.md"],
|
|
64
|
+
requiresExistingGraph: true,
|
|
65
|
+
toolName: "graph_suggest_concept_objective",
|
|
66
|
+
toolDescription: "Propose metadata.graphConcept patch (primary intent type, statement, business objective, outcome) for product UIs. No graph JSON returned.",
|
|
67
|
+
validateOutput: validateSuggestConceptOutput,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
action: "suggestCatalogResolution",
|
|
71
|
+
promptFile: "action-suggest-catalog-resolution.md",
|
|
72
|
+
sharedIncludes: [
|
|
73
|
+
"shared/request-context.md",
|
|
74
|
+
"shared/graph-format.md",
|
|
75
|
+
"shared/skill-selection.md",
|
|
76
|
+
"shared/structural-validation.md",
|
|
77
|
+
],
|
|
78
|
+
requiresExistingGraph: true,
|
|
79
|
+
toolName: "graph_suggest_catalog_resolution",
|
|
80
|
+
toolDescription: "Recommend catalog bindings (skills, scoping maps / questionId, narrix) from candidate lists; report gaps. No graph JSON returned.",
|
|
81
|
+
validateOutput: (out, ctx) => {
|
|
82
|
+
validateSuggestCatalogResolutionOutput(out, ctx);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
action: "suggestCatalogCreations",
|
|
87
|
+
promptFile: "action-suggest-catalog-creations.md",
|
|
88
|
+
sharedIncludes: [
|
|
89
|
+
"shared/request-context.md",
|
|
90
|
+
"shared/graph-format.md",
|
|
91
|
+
],
|
|
92
|
+
requiresExistingGraph: true,
|
|
93
|
+
toolName: "graph_suggest_catalog_creations",
|
|
94
|
+
toolDescription: "Propose new managed-catalog entries (catalogRequests-shaped) and optional new AI skills; host applies via Catalox (or your catalog store) after approval. No graph JSON returned.",
|
|
95
|
+
validateOutput: (out, ctx) => {
|
|
96
|
+
validateSuggestCatalogCreationsOutput(out, ctx);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
action: "suggestScopingNeedMatch",
|
|
101
|
+
promptFile: "action-suggest-scoping-need-match.md",
|
|
102
|
+
sharedIncludes: ["shared/request-context.md"],
|
|
103
|
+
requiresExistingGraph: false,
|
|
104
|
+
toolName: "graph_suggest_scoping_need_match",
|
|
105
|
+
toolDescription: "Match a natural-language scoping data need against catalogCandidates.scopingMaps; return best scopingMapId/questionId or no fit. No graph required. No graph JSON returned.",
|
|
106
|
+
validateOutput: (out, ctx) => {
|
|
107
|
+
validateSuggestScopingNeedMatchOutput(out, ctx);
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
action: "suggestScopingMapCreation",
|
|
112
|
+
promptFile: "action-suggest-scoping-map-creation.md",
|
|
113
|
+
sharedIncludes: ["shared/request-context.md", "shared/graph-format.md"],
|
|
114
|
+
requiresExistingGraph: false,
|
|
115
|
+
toolName: "graph_suggest_scoping_map_creation",
|
|
116
|
+
toolDescription: "Propose a new xmemory scoping map (scopingMapProposal + catalogRequestProposals) for MetaDB; host applies via CRUD after approval. No graph JSON returned.",
|
|
117
|
+
validateOutput: (out, ctx) => {
|
|
118
|
+
validateSuggestScopingMapCreationOutput(out, ctx);
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
action: "reviewConcept",
|
|
123
|
+
promptFile: "action-review-concept.md",
|
|
124
|
+
sharedIncludes: [
|
|
125
|
+
"shared/request-context.md",
|
|
126
|
+
"shared/graph-format.md",
|
|
127
|
+
"shared/skill-selection.md",
|
|
128
|
+
],
|
|
129
|
+
requiresExistingGraph: true,
|
|
130
|
+
toolName: "graph_review_concept",
|
|
131
|
+
toolDescription: "Review whether the graph concept makes sense; return verdict, categorized findings with severity, and improvement suggestions. No graph JSON returned.",
|
|
132
|
+
validateOutput: validateReviewConceptOutput,
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
const byAction = Object.fromEntries(GRAPH_COMPOSER_ACTION_REGISTRY.map((d) => [d.action, d]));
|
|
136
|
+
const byToolName = Object.fromEntries(GRAPH_COMPOSER_ACTION_REGISTRY.map((d) => [d.toolName, d]));
|
|
137
|
+
export function getActionDefinition(action) {
|
|
138
|
+
const d = byAction[action];
|
|
139
|
+
if (!d) {
|
|
140
|
+
throw new Error(`Unknown graph-composer action "${action}". Registered: ${GRAPH_COMPOSER_ACTION_REGISTRY.map((x) => x.action).join(", ")}`);
|
|
141
|
+
}
|
|
142
|
+
return d;
|
|
143
|
+
}
|
|
144
|
+
export function getActionDefinitionByToolName(toolName) {
|
|
145
|
+
return byToolName[toolName];
|
|
146
|
+
}
|
|
147
|
+
/** Ordered prompt paths that must exist on disk (for verify-local). */
|
|
148
|
+
export function requiredPromptPathsFromRegistry() {
|
|
149
|
+
const set = new Set();
|
|
150
|
+
for (const d of GRAPH_COMPOSER_ACTION_REGISTRY) {
|
|
151
|
+
set.add(d.promptFile);
|
|
152
|
+
for (const s of d.sharedIncludes)
|
|
153
|
+
set.add(s);
|
|
154
|
+
}
|
|
155
|
+
set.add("orchestrator-system.md");
|
|
156
|
+
return [...set].sort();
|
|
157
|
+
}
|
|
158
|
+
export function loadWorkerBaseMarkdown(action) {
|
|
159
|
+
const hit = workerBaseMarkdownCache.get(action);
|
|
160
|
+
if (hit !== undefined)
|
|
161
|
+
return hit;
|
|
162
|
+
const def = getActionDefinition(action);
|
|
163
|
+
const parts = def.sharedIncludes.map((rel) => readPromptRelative(rel).trimEnd());
|
|
164
|
+
parts.push(readPromptRelative(def.promptFile).trimEnd());
|
|
165
|
+
const built = parts.join("\n\n");
|
|
166
|
+
workerBaseMarkdownCache.set(action, built);
|
|
167
|
+
return built;
|
|
168
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type GraphComposerAction } from "./graphComposerActions.js";
|
|
2
|
+
import { type RunGraphComposerOptions } from "./runGraphComposer.js";
|
|
3
|
+
import type { GraphComposerAgentInput } from "./types.js";
|
|
4
|
+
export type GraphComposerAgentOrchestrationStep = {
|
|
5
|
+
kind: "call_tool";
|
|
6
|
+
tool: string;
|
|
7
|
+
action: GraphComposerAction;
|
|
8
|
+
};
|
|
9
|
+
export type GraphComposerAgentResult = {
|
|
10
|
+
orchestration: {
|
|
11
|
+
summary: string;
|
|
12
|
+
steps: GraphComposerAgentOrchestrationStep[];
|
|
13
|
+
};
|
|
14
|
+
/** Last worker JSON result, or `null` if the orchestrator finished without calling a tool. */
|
|
15
|
+
result: unknown | null;
|
|
16
|
+
};
|
|
17
|
+
export type RunGraphComposerAgentOptions = RunGraphComposerOptions & {
|
|
18
|
+
/** Upper bound on orchestrator JSON steps (each step may invoke one worker). Default 8. */
|
|
19
|
+
maxOrchestratorSteps?: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Orchestrator: chooses registered graph workers via structured JSON steps (`runJsonCompletion`),
|
|
23
|
+
* then runs each selection with `runGraphWorker` (same prompts as direct `runGraphComposer`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function runGraphComposerAgent(input: GraphComposerAgentInput, options?: RunGraphComposerAgentOptions): Promise<GraphComposerAgentResult>;
|
|
26
|
+
//# sourceMappingURL=graphComposerAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphComposerAgent.d.ts","sourceRoot":"","sources":["../src/graphComposerAgent.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAEV,uBAAuB,EAKxB,MAAM,YAAY,CAAC;AAyGpB,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,aAAa,EAAE;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,mCAAmC,EAAE,CAAC;KAC9C,CAAC;IACF,8FAA8F;IAC9F,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,GAAG;IACnE,2FAA2F;IAC3F,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAwBF;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,wBAAwB,CAAC,CAmGnC"}
|