@equinor/fusion-framework-cli-plugin-ai-base 2.0.1 → 4.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/CHANGELOG.md +30 -0
- package/README.md +18 -26
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/options/options.js +43 -86
- package/dist/esm/options/options.js.map +1 -1
- package/dist/esm/options/schema.js +14 -55
- package/dist/esm/options/schema.js.map +1 -1
- package/dist/esm/options/types.js +0 -9
- package/dist/esm/options/types.js.map +1 -1
- package/dist/esm/options/with-options.js +31 -89
- package/dist/esm/options/with-options.js.map +1 -1
- package/dist/esm/setup-framework.js +45 -62
- package/dist/esm/setup-framework.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/options/options.d.ts +24 -84
- package/dist/types/options/schema.d.ts +13 -28
- package/dist/types/options/types.d.ts +19 -36
- package/dist/types/options/with-options.d.ts +13 -26
- package/dist/types/setup-framework.d.ts +13 -27
- package/dist/types/version.d.ts +1 -1
- package/package.json +5 -5
- package/src/index.ts +1 -1
- package/src/options/options.ts +55 -109
- package/src/options/schema.ts +14 -63
- package/src/options/types.ts +19 -37
- package/src/options/with-options.ts +38 -130
- package/src/setup-framework.ts +52 -88
- package/src/version.ts +1 -1
- package/tsconfig.json +3 -0
package/src/options/schema.ts
CHANGED
|
@@ -1,77 +1,28 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Zod validation schema and inferred type for AI command options.
|
|
3
|
-
*
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
1
|
import z from 'zod';
|
|
8
2
|
|
|
9
3
|
/**
|
|
10
|
-
* Base Zod schema for AI
|
|
4
|
+
* Base Zod schema for Fusion AI command options.
|
|
11
5
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* All fields are optional — when omitted the service URL and token are
|
|
7
|
+
* resolved automatically from Fusion service discovery and MSAL auth.
|
|
14
8
|
*
|
|
15
9
|
* @example
|
|
16
10
|
* ```ts
|
|
17
|
-
* import { AiOptionsSchema } from '@equinor/fusion-framework-cli-plugin-ai-base';
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* const MyCommandOptionsSchema = AiOptionsSchema.extend({
|
|
21
|
-
* myOption: z.string(),
|
|
22
|
-
* });
|
|
11
|
+
* import { AiOptionsSchema } from '@equinor/fusion-framework-cli-plugin-ai-base/command-options';
|
|
12
|
+
* const MySchema = AiOptionsSchema.extend({ extra: z.string() });
|
|
23
13
|
* ```
|
|
24
14
|
*/
|
|
25
15
|
export const AiOptionsSchema = z
|
|
26
16
|
.object({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.describe('Azure OpenAI API version'),
|
|
36
|
-
openaiInstance: z
|
|
37
|
-
.string({ message: 'Azure OpenAI instance name is required and must be a non-empty string.' })
|
|
38
|
-
.min(1, 'Instance name must be a non-empty string.')
|
|
39
|
-
.describe('Azure OpenAI instance name'),
|
|
40
|
-
|
|
41
|
-
// Optional AI options
|
|
42
|
-
openaiChatDeployment: z
|
|
43
|
-
.string()
|
|
44
|
-
.min(1, 'Chat deployment name must be a non-empty string.')
|
|
45
|
-
.optional()
|
|
46
|
-
.describe('Azure OpenAI chat deployment name'),
|
|
47
|
-
openaiEmbeddingDeployment: z
|
|
48
|
-
.string()
|
|
49
|
-
.min(1, 'Embedding deployment name must be a non-empty string.')
|
|
50
|
-
.optional()
|
|
51
|
-
.describe('Azure OpenAI embedding deployment name'),
|
|
52
|
-
azureSearchEndpoint: z
|
|
53
|
-
.string()
|
|
54
|
-
.url('Azure Search endpoint must be a valid URL.')
|
|
55
|
-
.min(1, 'Azure Search endpoint must be a non-empty string.')
|
|
56
|
-
.optional()
|
|
57
|
-
.describe('Azure Search endpoint URL'),
|
|
58
|
-
azureSearchApiKey: z
|
|
59
|
-
.string()
|
|
60
|
-
.min(1, 'Azure Search API key must be a non-empty string.')
|
|
61
|
-
.optional()
|
|
62
|
-
.describe('Azure Search API key'),
|
|
63
|
-
azureSearchIndexName: z
|
|
64
|
-
.string()
|
|
65
|
-
.min(1, 'Azure Search index name must be a non-empty string.')
|
|
66
|
-
.optional()
|
|
67
|
-
.describe('Azure Search index name'),
|
|
17
|
+
env: z.string().optional(),
|
|
18
|
+
token: z.string().optional(),
|
|
19
|
+
tenantId: z.string().optional(),
|
|
20
|
+
clientId: z.string().optional(),
|
|
21
|
+
chatModel: z.string().min(1).optional(),
|
|
22
|
+
embedModel: z.string().min(1).optional(),
|
|
23
|
+
indexName: z.string().min(1).optional(),
|
|
24
|
+
debug: z.coerce.boolean().default(false),
|
|
68
25
|
})
|
|
69
|
-
.describe('Base AI
|
|
26
|
+
.describe('Base Fusion AI command options');
|
|
70
27
|
|
|
71
|
-
/**
|
|
72
|
-
* Type representing the validated AI options.
|
|
73
|
-
*
|
|
74
|
-
* This type is inferred from the Zod schema and should be used throughout AI plugins
|
|
75
|
-
* to ensure type safety and consistency with the schema.
|
|
76
|
-
*/
|
|
77
28
|
export type AiOptionsType = z.infer<typeof AiOptionsSchema>;
|
package/src/options/types.ts
CHANGED
|
@@ -1,42 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Base options for all Fusion AI CLI commands.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* For runtime validation prefer {@link AiOptionsSchema} from the schema module.
|
|
7
|
-
*
|
|
8
|
-
* @packageDocumentation
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Configuration options for AI-related CLI commands.
|
|
13
|
-
*
|
|
14
|
-
* This interface defines all available options for configuring Azure OpenAI services
|
|
15
|
-
* and Azure Cognitive Search integration. Required fields must be provided either
|
|
16
|
-
* via command-line arguments or environment variables. Optional fields enable
|
|
17
|
-
* specific features (chat, embeddings, vector search) when provided.
|
|
18
|
-
*
|
|
19
|
-
* @remarks
|
|
20
|
-
* - All required fields (apiKey, apiVersion, instance) must be provided for any AI operation
|
|
21
|
-
* - Chat operations require `openaiChatDeployment`
|
|
22
|
-
* - Embedding operations require `openaiEmbeddingDeployment`
|
|
23
|
-
* - Vector search requires all three Azure Search fields plus `openaiEmbeddingDeployment`
|
|
4
|
+
* The service URL and token are resolved automatically from Fusion
|
|
5
|
+
* service discovery using the provided environment and authentication options.
|
|
24
6
|
*/
|
|
25
7
|
export interface AiOptions {
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
/** Azure
|
|
31
|
-
|
|
32
|
-
/** Azure
|
|
33
|
-
|
|
34
|
-
/** Azure OpenAI
|
|
35
|
-
|
|
36
|
-
/** Azure
|
|
37
|
-
|
|
38
|
-
/** Azure
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
|
|
8
|
+
/** Fusion environment used for service discovery (e.g. `ci`, `fprd`). */
|
|
9
|
+
env?: string;
|
|
10
|
+
/** Bearer token passed directly to the auth module (overrides clientId/tenantId). */
|
|
11
|
+
token?: string;
|
|
12
|
+
/** Azure AD tenant ID for MSAL silent authentication. */
|
|
13
|
+
tenantId?: string;
|
|
14
|
+
/** Azure AD client ID for MSAL silent authentication. */
|
|
15
|
+
clientId?: string;
|
|
16
|
+
/** Azure OpenAI chat model deployment name. Required for chat operations. */
|
|
17
|
+
chatModel?: string;
|
|
18
|
+
/** Azure OpenAI embedding model deployment name. Required for embedding and index operations. */
|
|
19
|
+
embedModel?: string;
|
|
20
|
+
/** Azure AI Search index name. Required for vector search / indexing operations. */
|
|
21
|
+
indexName?: string;
|
|
22
|
+
/** Enable debug mode for verbose logging. */
|
|
23
|
+
debug?: boolean;
|
|
42
24
|
}
|
|
@@ -1,159 +1,67 @@
|
|
|
1
1
|
import { type Command, InvalidOptionArgumentError } from 'commander';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
chatModelOption,
|
|
4
|
+
clientIdOption,
|
|
5
|
+
debugOption,
|
|
6
|
+
embedModelOption,
|
|
7
|
+
envOption,
|
|
8
|
+
indexNameOption,
|
|
9
|
+
tenantIdOption,
|
|
10
|
+
tokenOption,
|
|
11
11
|
} from './options.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Enhances a Commander command with AI
|
|
14
|
+
* Enhances a Commander command with Fusion AI options and validation.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* based on the command's requirements.
|
|
16
|
+
* Core auth options (`--env`, `--token`, `--tenant-id`, `--client-id`) are always
|
|
17
|
+
* added. When no explicit `--token` is provided, the framework will authenticate
|
|
18
|
+
* via MSAL and resolve the AI service endpoint from Fusion service discovery.
|
|
20
19
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* - Chat: `openaiChatDeployment` (if includeChat is true)
|
|
24
|
-
* - Embedding: `openaiEmbeddingDeployment` (if includeEmbedding is true)
|
|
25
|
-
* - Search: `azureSearchEndpoint`, `azureSearchApiKey`, `azureSearchIndexName` (if includeSearch is true)
|
|
20
|
+
* Pass flags to include optional chat, embed, or index options and make
|
|
21
|
+
* them required at runtime via the `preAction` validation hook.
|
|
26
22
|
*
|
|
27
|
-
* @param command - The Commander command
|
|
28
|
-
* @param args -
|
|
29
|
-
* @param args.
|
|
30
|
-
* @param args.
|
|
31
|
-
* @param args.includeSearch -
|
|
32
|
-
* @returns The
|
|
33
|
-
* @throws {InvalidOptionArgumentError} During command execution if required options are missing or invalid
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts
|
|
37
|
-
* const chatCommand = createCommand('chat')
|
|
38
|
-
* .description('Start a chat session');
|
|
39
|
-
*
|
|
40
|
-
* withOptions(chatCommand, { includeChat: true });
|
|
41
|
-
* ```
|
|
23
|
+
* @param command - The Commander command to decorate with options.
|
|
24
|
+
* @param args - Feature flags controlling which optional options to add.
|
|
25
|
+
* @param args.includeChat - Add `--chat-model` and validate it at runtime.
|
|
26
|
+
* @param args.includeEmbedding - Add `--embed-model` and validate it at runtime.
|
|
27
|
+
* @param args.includeSearch - Add `--index-name` and validate it at runtime.
|
|
28
|
+
* @returns The decorated command.
|
|
42
29
|
*/
|
|
43
30
|
export const withOptions = (
|
|
44
31
|
command: Command,
|
|
45
32
|
args?: Partial<{
|
|
46
|
-
includeEmbedding: boolean;
|
|
47
33
|
includeChat: boolean;
|
|
34
|
+
includeEmbedding: boolean;
|
|
48
35
|
includeSearch: boolean;
|
|
49
36
|
}>,
|
|
50
37
|
): Command => {
|
|
51
|
-
|
|
52
|
-
command.addOption(
|
|
53
|
-
command.addOption(
|
|
54
|
-
command.addOption(
|
|
55
|
-
|
|
56
|
-
// Deployment options
|
|
57
|
-
if (args?.includeChat === true) {
|
|
58
|
-
command.addOption(chatDeploymentOption);
|
|
59
|
-
}
|
|
38
|
+
command.addOption(envOption);
|
|
39
|
+
command.addOption(tokenOption);
|
|
40
|
+
command.addOption(tenantIdOption);
|
|
41
|
+
command.addOption(clientIdOption);
|
|
42
|
+
command.addOption(debugOption);
|
|
60
43
|
|
|
61
|
-
if (args?.
|
|
62
|
-
|
|
63
|
-
|
|
44
|
+
if (args?.includeChat) command.addOption(chatModelOption);
|
|
45
|
+
if (args?.includeEmbedding) command.addOption(embedModelOption);
|
|
46
|
+
if (args?.includeSearch) command.addOption(indexNameOption);
|
|
64
47
|
|
|
65
|
-
// Azure Search options
|
|
66
|
-
if (args?.includeSearch === true) {
|
|
67
|
-
command.addOption(azureSearchEndpointOption);
|
|
68
|
-
command.addOption(azureSearchApiKeyOption);
|
|
69
|
-
command.addOption(azureSearchIndexNameOption);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Validation hook
|
|
73
48
|
command.hook('preAction', (thisCommand) => {
|
|
74
|
-
const
|
|
49
|
+
const opts = thisCommand.opts();
|
|
75
50
|
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
!options.openaiApiKey ||
|
|
79
|
-
typeof options.openaiApiKey !== 'string' ||
|
|
80
|
-
options.openaiApiKey.trim() === ''
|
|
81
|
-
) {
|
|
51
|
+
if (args?.includeChat && !opts.chatModel?.trim()) {
|
|
82
52
|
throw new InvalidOptionArgumentError(
|
|
83
|
-
'
|
|
53
|
+
'Chat model name is required. Provide --chat-model or set FUSION_AI_CHAT_MODEL.',
|
|
84
54
|
);
|
|
85
55
|
}
|
|
86
|
-
|
|
87
|
-
// Validate API version
|
|
88
|
-
if (!options.openaiApiVersion || typeof options.openaiApiVersion !== 'string') {
|
|
89
|
-
throw new InvalidOptionArgumentError('API version must be a non-empty string.');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Validate instance name
|
|
93
|
-
if (
|
|
94
|
-
!options.openaiInstance ||
|
|
95
|
-
typeof options.openaiInstance !== 'string' ||
|
|
96
|
-
options.openaiInstance.trim() === ''
|
|
97
|
-
) {
|
|
56
|
+
if (args?.includeEmbedding && !opts.embedModel?.trim()) {
|
|
98
57
|
throw new InvalidOptionArgumentError(
|
|
99
|
-
'
|
|
58
|
+
'Embedding model name is required. Provide --embed-model or set FUSION_AI_EMBED_MODEL.',
|
|
100
59
|
);
|
|
101
60
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
typeof options.openaiChatDeployment !== 'string' ||
|
|
107
|
-
options.openaiChatDeployment.trim() === ''
|
|
108
|
-
) {
|
|
109
|
-
throw new InvalidOptionArgumentError(
|
|
110
|
-
'Chat deployment name is required and must be a non-empty string.',
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (args?.includeEmbedding === true) {
|
|
116
|
-
if (
|
|
117
|
-
!options.openaiEmbeddingDeployment ||
|
|
118
|
-
typeof options.openaiEmbeddingDeployment !== 'string' ||
|
|
119
|
-
options.openaiEmbeddingDeployment.trim() === ''
|
|
120
|
-
) {
|
|
121
|
-
throw new InvalidOptionArgumentError(
|
|
122
|
-
'Azure OpenAI embedding deployment name is required. Provide it via --openai-embedding-deployment option or AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME environment variable.',
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (args?.includeSearch === true) {
|
|
128
|
-
if (
|
|
129
|
-
!options.azureSearchEndpoint ||
|
|
130
|
-
typeof options.azureSearchEndpoint !== 'string' ||
|
|
131
|
-
options.azureSearchEndpoint.trim() === ''
|
|
132
|
-
) {
|
|
133
|
-
throw new InvalidOptionArgumentError(
|
|
134
|
-
'Azure Search endpoint is required and must be a non-empty string.',
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (
|
|
139
|
-
!options.azureSearchApiKey ||
|
|
140
|
-
typeof options.azureSearchApiKey !== 'string' ||
|
|
141
|
-
options.azureSearchApiKey.trim() === ''
|
|
142
|
-
) {
|
|
143
|
-
throw new InvalidOptionArgumentError(
|
|
144
|
-
'Azure Search API key is required. Provide it via --azure-search-api-key option or AZURE_SEARCH_API_KEY environment variable.',
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
!options.azureSearchIndexName ||
|
|
150
|
-
typeof options.azureSearchIndexName !== 'string' ||
|
|
151
|
-
options.azureSearchIndexName.trim() === ''
|
|
152
|
-
) {
|
|
153
|
-
throw new InvalidOptionArgumentError(
|
|
154
|
-
'Azure Search index name is required and must be a non-empty string.',
|
|
155
|
-
);
|
|
156
|
-
}
|
|
61
|
+
if (args?.includeSearch && !opts.indexName?.trim()) {
|
|
62
|
+
throw new InvalidOptionArgumentError(
|
|
63
|
+
'Index name is required. Provide --index-name or set FUSION_AI_INDEX_NAME.',
|
|
64
|
+
);
|
|
157
65
|
}
|
|
158
66
|
});
|
|
159
67
|
|
package/src/setup-framework.ts
CHANGED
|
@@ -1,107 +1,71 @@
|
|
|
1
|
-
import { enableAI
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
AzureOpenAiEmbed,
|
|
5
|
-
AzureOpenAIModel,
|
|
6
|
-
AzureVectorStore,
|
|
7
|
-
} from '@equinor/fusion-framework-module-ai/azure';
|
|
1
|
+
import { enableAI } from '@equinor/fusion-framework-module-ai';
|
|
2
|
+
import type { AIModule } from '@equinor/fusion-framework-module-ai';
|
|
8
3
|
|
|
4
|
+
import { initializeFramework, FusionEnv } from '@equinor/fusion-framework-cli/bin';
|
|
5
|
+
import type { FusionFrameworkSettings, FusionFramework } from '@equinor/fusion-framework-cli/bin';
|
|
9
6
|
import type { AiOptions } from './options/index.js';
|
|
10
|
-
import { ModulesConfigurator, type ModulesInstance } from '@equinor/fusion-framework-module';
|
|
11
7
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
* This type represents an initialized Fusion Framework instance that includes
|
|
16
|
-
* the AI module, providing access to chat models, embedding services, and
|
|
17
|
-
* vector stores configured via the setup process.
|
|
18
|
-
*/
|
|
19
|
-
export type FrameworkInstance = ModulesInstance<[AIModule]>;
|
|
8
|
+
/** Initialized framework instance with the AI module. */
|
|
9
|
+
export type FrameworkInstance = FusionFramework<[AIModule]>;
|
|
20
10
|
|
|
21
11
|
/**
|
|
22
|
-
*
|
|
12
|
+
* Creates a Fusion Framework instance with the AI module enabled.
|
|
23
13
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
14
|
+
* Uses Azure Identity's `DefaultAzureCredential` by default, which resolves
|
|
15
|
+
* credentials from the environment (OIDC, managed identity, Azure CLI, etc.).
|
|
16
|
+
* When an explicit token is provided via `--token` or `FUSION_TOKEN`, that
|
|
17
|
+
* token is used directly instead.
|
|
27
18
|
*
|
|
28
|
-
* @param options -
|
|
29
|
-
* @
|
|
30
|
-
* @
|
|
31
|
-
* @param options.openaiInstance - Azure OpenAI instance name
|
|
32
|
-
* @param options.openaiChatDeployment - Optional chat model deployment name
|
|
33
|
-
* @param options.openaiEmbeddingDeployment - Optional embedding model deployment name
|
|
34
|
-
* @param options.azureSearchEndpoint - Optional Azure Search service endpoint URL
|
|
35
|
-
* @param options.azureSearchApiKey - Optional Azure Search API key
|
|
36
|
-
* @param options.azureSearchIndexName - Optional Azure Search index name
|
|
37
|
-
* @returns Promise resolving to an initialized framework instance with AI module configured
|
|
38
|
-
* @throws {Error} If embedding deployment is required but not provided when configuring vector store
|
|
39
|
-
* @throws {Error} If embedding service cannot be retrieved for vector store configuration
|
|
19
|
+
* @param options - CLI options resolved by {@link withOptions}.
|
|
20
|
+
* @returns A fully initialised framework instance with the AI module.
|
|
21
|
+
* @throws {Error} When authentication fails after the interactive retry.
|
|
40
22
|
*/
|
|
41
|
-
export const setupFramework = async (options: AiOptions): Promise<
|
|
42
|
-
|
|
43
|
-
const configurator = new ModulesConfigurator<[AIModule]>();
|
|
23
|
+
export const setupFramework = async (options: AiOptions): Promise<FusionFramework<[AIModule]>> => {
|
|
24
|
+
const debug = options.debug ?? false;
|
|
44
25
|
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
new AzureOpenAIModel({
|
|
52
|
-
azureOpenAIApiKey: options.openaiApiKey,
|
|
53
|
-
azureOpenAIApiDeploymentName: options.openaiChatDeployment,
|
|
54
|
-
azureOpenAIApiInstanceName: options.openaiInstance,
|
|
55
|
-
azureOpenAIApiVersion: options.openaiApiVersion,
|
|
56
|
-
}),
|
|
57
|
-
);
|
|
58
|
-
}
|
|
26
|
+
// Auth strategy:
|
|
27
|
+
// 1. Explicit token (--token / FUSION_TOKEN) → direct token passthrough
|
|
28
|
+
// 2. Everything else → Azure Identity (DefaultAzureCredential)
|
|
29
|
+
const auth: FusionFrameworkSettings['auth'] = options.token
|
|
30
|
+
? { token: options.token }
|
|
31
|
+
: { defaultCredential: true };
|
|
59
32
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
azureOpenAIApiDeploymentName: options.openaiEmbeddingDeployment,
|
|
67
|
-
azureOpenAIApiInstanceName: options.openaiInstance,
|
|
68
|
-
azureOpenAIApiVersion: options.openaiApiVersion,
|
|
69
|
-
}),
|
|
70
|
-
);
|
|
71
|
-
}
|
|
33
|
+
const env = (options.env as FusionEnv) ?? FusionEnv.ContinuesIntegration;
|
|
34
|
+
|
|
35
|
+
if (debug) {
|
|
36
|
+
console.debug('[debug] Environment:', env);
|
|
37
|
+
console.debug('[debug] Auth mode:', options.token ? 'static-token' : 'azure-identity');
|
|
38
|
+
}
|
|
72
39
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
if (!options.openaiEmbeddingDeployment) {
|
|
77
|
-
throw new Error('Embedding deployment is required to configure the vector store');
|
|
78
|
-
}
|
|
40
|
+
/** Initialise the framework, resolve the AI service, and pre-cache tokens. */
|
|
41
|
+
const initAndSetup = async (): Promise<FusionFramework<[AIModule]>> => {
|
|
42
|
+
if (debug) console.debug('[debug] Initializing framework with AI module…');
|
|
79
43
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
44
|
+
const framework = await initializeFramework<[AIModule]>({ env, auth }, (configurator) => {
|
|
45
|
+
enableAI(configurator);
|
|
46
|
+
});
|
|
83
47
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
}
|
|
48
|
+
// resolveService makes an authenticated HTTP call — will throw
|
|
49
|
+
// NoAccountsError if the user has never logged in.
|
|
50
|
+
const service = await framework.serviceDiscovery.resolveService('ai');
|
|
51
|
+
const scopes = service.scopes ?? service.defaultScopes ?? [];
|
|
90
52
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
endpoint: options.azureSearchEndpoint,
|
|
95
|
-
key: options.azureSearchApiKey,
|
|
96
|
-
indexName: options.azureSearchIndexName,
|
|
97
|
-
}),
|
|
98
|
-
);
|
|
53
|
+
if (debug) {
|
|
54
|
+
console.debug('[debug] AI service URL:', service.uri);
|
|
55
|
+
console.debug('[debug] AI service scopes:', scopes);
|
|
99
56
|
}
|
|
100
|
-
});
|
|
101
57
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
58
|
+
// Pre-cache a token for the AI service scopes so strategy callbacks
|
|
59
|
+
// don't attempt (and fail) a silent acquisition later.
|
|
60
|
+
const token = await framework.auth.acquireAccessToken({ request: { scopes } });
|
|
61
|
+
if (!token) throw new Error('Failed to acquire access token for the AI service.');
|
|
62
|
+
|
|
63
|
+
if (debug) console.debug('[debug] Token acquired successfully');
|
|
64
|
+
|
|
65
|
+
return framework;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return await initAndSetup();
|
|
105
69
|
};
|
|
106
70
|
|
|
107
71
|
export default setupFramework;
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '
|
|
2
|
+
export const version = '4.0.0';
|