@equinor/fusion-framework-cli-plugin-ai-base 2.0.1 → 3.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.
@@ -1,72 +1,82 @@
1
1
  import { enableAI } from '@equinor/fusion-framework-module-ai';
2
- import { AzureOpenAiEmbed, AzureOpenAIModel, AzureVectorStore, } from '@equinor/fusion-framework-module-ai/azure';
3
- import { ModulesConfigurator } from '@equinor/fusion-framework-module';
2
+ import { initializeFramework, FusionEnv } from '@equinor/fusion-framework-cli/bin';
3
+ import { execFileSync } from 'node:child_process';
4
4
  /**
5
- * Initializes and configures the Fusion Framework with AI module capabilities.
5
+ * Check whether an error (possibly wrapped in a cause chain) is an
6
+ * authentication-related failure that may be recoverable via interactive login.
6
7
  *
7
- * Sets up the framework with Azure OpenAI chat models, embedding services, and
8
- * optionally Azure Cognitive Search vector stores. The function handles the complete
9
- * initialization process including service registration and dependency injection.
8
+ * @internal
9
+ */
10
+ const isAuthError = (error) => {
11
+ let current = error;
12
+ while (current) {
13
+ if (current instanceof Error) {
14
+ if (current.name === 'NoAccountsError' ||
15
+ current.name === 'SilentTokenAcquisitionError' ||
16
+ current.message.includes('No accounts found')) {
17
+ return true;
18
+ }
19
+ }
20
+ current = current.cause;
21
+ }
22
+ return false;
23
+ };
24
+ /**
25
+ * Creates a Fusion Framework instance with the AI module enabled.
10
26
  *
11
- * @param options - AI configuration options
12
- * @param options.openaiApiKey - Azure OpenAI API key for authentication
13
- * @param options.openaiApiVersion - Azure OpenAI API version (e.g., '2024-02-15-preview')
14
- * @param options.openaiInstance - Azure OpenAI instance name
15
- * @param options.openaiChatDeployment - Optional chat model deployment name
16
- * @param options.openaiEmbeddingDeployment - Optional embedding model deployment name
17
- * @param options.azureSearchEndpoint - Optional Azure Search service endpoint URL
18
- * @param options.azureSearchApiKey - Optional Azure Search API key
19
- * @param options.azureSearchIndexName - Optional Azure Search index name
20
- * @returns Promise resolving to an initialized framework instance with AI module configured
21
- * @throws {Error} If embedding deployment is required but not provided when configuring vector store
22
- * @throws {Error} If embedding service cannot be retrieved for vector store configuration
27
+ * Initialises the Fusion Framework with service discovery and MSAL auth,
28
+ * resolves the `'ai'` service endpoint, and pre-caches a bearer token.
29
+ * If MSAL has no cached credentials, the CLI's interactive `auth login`
30
+ * flow is spawned automatically before retrying.
31
+ *
32
+ * @param options - CLI options resolved by {@link withOptions}.
33
+ * @returns A fully initialised framework instance with the AI module.
34
+ * @throws {Error} When authentication fails after the interactive retry.
23
35
  */
24
36
  export const setupFramework = async (options) => {
25
- // Create a new module configurator for the framework
26
- const configurator = new ModulesConfigurator();
27
- // Configure AI module with provided options
28
- enableAI(configurator, (aiConfig) => {
29
- // Configure chat model if deployment name is provided
30
- if (options.openaiChatDeployment) {
31
- aiConfig.setModel(options.openaiChatDeployment, new AzureOpenAIModel({
32
- azureOpenAIApiKey: options.openaiApiKey,
33
- azureOpenAIApiDeploymentName: options.openaiChatDeployment,
34
- azureOpenAIApiInstanceName: options.openaiInstance,
35
- azureOpenAIApiVersion: options.openaiApiVersion,
36
- }));
37
- }
38
- // Configure embedding model if deployment name is provided
39
- if (options.openaiEmbeddingDeployment) {
40
- aiConfig.setEmbedding(options.openaiEmbeddingDeployment, new AzureOpenAiEmbed({
41
- azureOpenAIApiKey: options.openaiApiKey,
42
- azureOpenAIApiDeploymentName: options.openaiEmbeddingDeployment,
43
- azureOpenAIApiInstanceName: options.openaiInstance,
44
- azureOpenAIApiVersion: options.openaiApiVersion,
45
- }));
46
- }
47
- // Configure vector store if Azure Search options are provided
48
- // Vector store requires an embedding service to generate embeddings for documents
49
- if (options.azureSearchEndpoint && options.azureSearchApiKey && options.azureSearchIndexName) {
50
- if (!options.openaiEmbeddingDeployment) {
51
- throw new Error('Embedding deployment is required to configure the vector store');
52
- }
53
- // Retrieve the embedding service to pass to the vector store
54
- // The vector store uses embeddings to index and search documents
55
- const embeddingService = aiConfig.getService('embeddings', options.openaiEmbeddingDeployment);
56
- // Check that the embedding service was successfully retrieved
57
- if (!embeddingService) {
58
- throw new Error(`Embedding service '${options.openaiEmbeddingDeployment}' not found for vector store configuration`);
59
- }
60
- aiConfig.setVectorStore(options.azureSearchIndexName, new AzureVectorStore(embeddingService, {
61
- endpoint: options.azureSearchEndpoint,
62
- key: options.azureSearchApiKey,
63
- indexName: options.azureSearchIndexName,
64
- }));
37
+ // Service-discovery mode: resolve URL + scopes from Fusion service registry
38
+ const auth = options.token
39
+ ? { token: options.token }
40
+ : {
41
+ tenantId: options.tenantId ?? '3aa4a235-b6e2-48d5-9195-7fcf05b459b0',
42
+ clientId: options.clientId ?? 'a318b8e1-0295-4e17-98d5-35f67dfeba14',
43
+ };
44
+ const env = options.env ?? FusionEnv.ContinuesIntegration;
45
+ /** Initialise the framework, resolve the AI service, and pre-cache tokens. */
46
+ const initAndSetup = async () => {
47
+ const framework = await initializeFramework({ env, auth }, (configurator) => {
48
+ enableAI(configurator);
49
+ });
50
+ // resolveService makes an authenticated HTTP call will throw
51
+ // NoAccountsError if the user has never logged in.
52
+ const service = await framework.serviceDiscovery.resolveService('ai');
53
+ const scopes = service.scopes ?? service.defaultScopes ?? [];
54
+ // Pre-cache a token for the AI service scopes so strategy callbacks
55
+ // don't attempt (and fail) a silent acquisition later.
56
+ const token = await framework.auth.acquireAccessToken({ request: { scopes } });
57
+ if (!token)
58
+ throw new Error('Failed to acquire access token for the AI service.');
59
+ return framework;
60
+ };
61
+ try {
62
+ return await initAndSetup();
63
+ }
64
+ catch (error) {
65
+ // If the failure is auth-related and we're not using a static token,
66
+ // spawn the CLI's own `auth login` (starts local server + browser)
67
+ // and retry the full init sequence.
68
+ if (!isAuthError(error) || options.token)
69
+ throw error;
70
+ const cliEntry = process.argv[1];
71
+ if (!cliEntry) {
72
+ throw new Error('Failed to acquire access token and could not determine CLI path for interactive login.');
65
73
  }
66
- });
67
- // Initialize the framework with all configured modules
68
- const framework = await configurator.initialize();
69
- return framework;
74
+ console.log('No cached credentials — launching interactive login…');
75
+ execFileSync(process.execPath, [cliEntry, 'auth', 'login'], {
76
+ stdio: 'inherit',
77
+ });
78
+ return await initAndSetup();
79
+ }
70
80
  };
71
81
  export default setupFramework;
72
82
  //# sourceMappingURL=setup-framework.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup-framework.js","sourceRoot":"","sources":["../../src/setup-framework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuC,MAAM,qCAAqC,CAAC;AAEpG,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAwB,MAAM,kCAAkC,CAAC;AAW7F;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,OAAkB,EAA8B,EAAE;IACrF,qDAAqD;IACrD,MAAM,YAAY,GAAG,IAAI,mBAAmB,EAAc,CAAC;IAE3D,4CAA4C;IAC5C,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAyB,EAAE,EAAE;QACnD,sDAAsD;QACtD,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;YACjC,QAAQ,CAAC,QAAQ,CACf,OAAO,CAAC,oBAAoB,EAC5B,IAAI,gBAAgB,CAAC;gBACnB,iBAAiB,EAAE,OAAO,CAAC,YAAY;gBACvC,4BAA4B,EAAE,OAAO,CAAC,oBAAoB;gBAC1D,0BAA0B,EAAE,OAAO,CAAC,cAAc;gBAClD,qBAAqB,EAAE,OAAO,CAAC,gBAAgB;aAChD,CAAC,CACH,CAAC;QACJ,CAAC;QAED,2DAA2D;QAC3D,IAAI,OAAO,CAAC,yBAAyB,EAAE,CAAC;YACtC,QAAQ,CAAC,YAAY,CACnB,OAAO,CAAC,yBAAyB,EACjC,IAAI,gBAAgB,CAAC;gBACnB,iBAAiB,EAAE,OAAO,CAAC,YAAY;gBACvC,4BAA4B,EAAE,OAAO,CAAC,yBAAyB;gBAC/D,0BAA0B,EAAE,OAAO,CAAC,cAAc;gBAClD,qBAAqB,EAAE,OAAO,CAAC,gBAAgB;aAChD,CAAC,CACH,CAAC;QACJ,CAAC;QAED,8DAA8D;QAC9D,kFAAkF;QAClF,IAAI,OAAO,CAAC,mBAAmB,IAAI,OAAO,CAAC,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;YAC7F,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;YACpF,CAAC;YAED,6DAA6D;YAC7D,iEAAiE;YACjE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAE9F,8DAA8D;YAC9D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CACb,sBAAsB,OAAO,CAAC,yBAAyB,4CAA4C,CACpG,CAAC;YACJ,CAAC;YAED,QAAQ,CAAC,cAAc,CACrB,OAAO,CAAC,oBAAoB,EAC5B,IAAI,gBAAgB,CAAC,gBAAgB,EAAE;gBACrC,QAAQ,EAAE,OAAO,CAAC,mBAAmB;gBACrC,GAAG,EAAE,OAAO,CAAC,iBAAiB;gBAC9B,SAAS,EAAE,OAAO,CAAC,oBAAoB;aACxC,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,uDAAuD;IACvD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"setup-framework.js","sourceRoot":"","sources":["../../src/setup-framework.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  // Generated by genversion.
2
- export const version = '2.0.1';
2
+ export const version = '3.0.0';
3
3
  //# sourceMappingURL=version.js.map