@equinor/fusion-framework-cli-plugin-ai-base 3.0.0 → 4.0.1
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 +20 -0
- package/dist/esm/options/options.js +5 -0
- package/dist/esm/options/options.js.map +1 -1
- package/dist/esm/options/schema.js +1 -0
- package/dist/esm/options/schema.js.map +1 -1
- package/dist/esm/options/with-options.js +2 -1
- package/dist/esm/options/with-options.js.map +1 -1
- package/dist/esm/setup-framework.js +22 -49
- 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/options/options.d.ts +17 -14
- package/dist/types/options/schema.d.ts +1 -0
- package/dist/types/options/types.d.ts +2 -0
- package/dist/types/setup-framework.d.ts +4 -4
- package/dist/types/version.d.ts +1 -1
- package/package.json +7 -7
- package/src/options/options.ts +6 -0
- package/src/options/schema.ts +1 -0
- package/src/options/types.ts +2 -0
- package/src/options/with-options.ts +2 -0
- package/src/setup-framework.ts +25 -56
- package/src/version.ts +1 -1
- package/tsconfig.json +3 -1
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
/** `--env` | `FUSION_ENV` — Fusion environment for service discovery */
|
|
2
|
-
export declare const envOption: import("commander").Option;
|
|
2
|
+
export declare const envOption: import("node_modules/commander/typings/index.js").Option;
|
|
3
3
|
/** `--token` | `FUSION_TOKEN` — explicit bearer token */
|
|
4
|
-
export declare const tokenOption: import("commander").Option;
|
|
4
|
+
export declare const tokenOption: import("node_modules/commander/typings/index.js").Option;
|
|
5
5
|
/** `--tenant-id` | `FUSION_TENANT_ID` */
|
|
6
|
-
export declare const tenantIdOption: import("commander").Option;
|
|
6
|
+
export declare const tenantIdOption: import("node_modules/commander/typings/index.js").Option;
|
|
7
7
|
/** `--client-id` | `FUSION_CLIENT_ID` */
|
|
8
|
-
export declare const clientIdOption: import("commander").Option;
|
|
8
|
+
export declare const clientIdOption: import("node_modules/commander/typings/index.js").Option;
|
|
9
9
|
/** `--chat-model` | `FUSION_AI_CHAT_MODEL` */
|
|
10
|
-
export declare const chatModelOption: import("commander").Option;
|
|
10
|
+
export declare const chatModelOption: import("node_modules/commander/typings/index.js").Option;
|
|
11
11
|
/** `--embed-model` | `FUSION_AI_EMBED_MODEL` */
|
|
12
|
-
export declare const embedModelOption: import("commander").Option;
|
|
12
|
+
export declare const embedModelOption: import("node_modules/commander/typings/index.js").Option;
|
|
13
13
|
/** `--index-name` | `FUSION_AI_INDEX_NAME` */
|
|
14
|
-
export declare const indexNameOption: import("commander").Option;
|
|
14
|
+
export declare const indexNameOption: import("node_modules/commander/typings/index.js").Option;
|
|
15
|
+
/** `-d, --debug` | `RUNNER_DEBUG` — enable verbose logging */
|
|
16
|
+
export declare const debugOption: import("node_modules/commander/typings/index.js").Option;
|
|
15
17
|
declare const _default: {
|
|
16
|
-
envOption: import("commander").Option;
|
|
17
|
-
tokenOption: import("commander").Option;
|
|
18
|
-
tenantIdOption: import("commander").Option;
|
|
19
|
-
clientIdOption: import("commander").Option;
|
|
20
|
-
chatModelOption: import("commander").Option;
|
|
21
|
-
embedModelOption: import("commander").Option;
|
|
22
|
-
indexNameOption: import("commander").Option;
|
|
18
|
+
envOption: import("node_modules/commander/typings/index.js").Option;
|
|
19
|
+
tokenOption: import("node_modules/commander/typings/index.js").Option;
|
|
20
|
+
tenantIdOption: import("node_modules/commander/typings/index.js").Option;
|
|
21
|
+
clientIdOption: import("node_modules/commander/typings/index.js").Option;
|
|
22
|
+
chatModelOption: import("node_modules/commander/typings/index.js").Option;
|
|
23
|
+
embedModelOption: import("node_modules/commander/typings/index.js").Option;
|
|
24
|
+
indexNameOption: import("node_modules/commander/typings/index.js").Option;
|
|
25
|
+
debugOption: import("node_modules/commander/typings/index.js").Option;
|
|
23
26
|
};
|
|
24
27
|
export default _default;
|
|
@@ -19,5 +19,6 @@ export declare const AiOptionsSchema: z.ZodObject<{
|
|
|
19
19
|
chatModel: z.ZodOptional<z.ZodString>;
|
|
20
20
|
embedModel: z.ZodOptional<z.ZodString>;
|
|
21
21
|
indexName: z.ZodOptional<z.ZodString>;
|
|
22
|
+
debug: z.ZodDefault<z.z.ZodCoercedBoolean<unknown>>;
|
|
22
23
|
}, z.z.core.$strip>;
|
|
23
24
|
export type AiOptionsType = z.infer<typeof AiOptionsSchema>;
|
|
@@ -6,10 +6,10 @@ export type FrameworkInstance = FusionFramework<[AIModule]>;
|
|
|
6
6
|
/**
|
|
7
7
|
* Creates a Fusion Framework instance with the AI module enabled.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Uses Azure Identity's `DefaultAzureCredential` by default, which resolves
|
|
10
|
+
* credentials from the environment (OIDC, managed identity, Azure CLI, etc.).
|
|
11
|
+
* When an explicit token is provided via `--token` or `FUSION_TOKEN`, that
|
|
12
|
+
* token is used directly instead.
|
|
13
13
|
*
|
|
14
14
|
* @param options - CLI options resolved by {@link withOptions}.
|
|
15
15
|
* @returns A fully initialised framework instance with the AI module.
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "
|
|
1
|
+
export declare const version = "4.0.1";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-cli-plugin-ai-base",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Base AI plugin package for Fusion Framework CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/esm/index.js",
|
|
@@ -44,18 +44,18 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"commander": "^14.0.1",
|
|
47
|
-
"zod": "^4.3
|
|
47
|
+
"zod": "^4.4.3",
|
|
48
|
+
"@equinor/fusion-framework-module-ai": "4.0.0",
|
|
48
49
|
"@equinor/fusion-framework-module": "6.0.0",
|
|
49
|
-
"@equinor/fusion-imports": "2.0.0"
|
|
50
|
-
"@equinor/fusion-framework-module-ai": "4.0.0"
|
|
50
|
+
"@equinor/fusion-imports": "2.0.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@equinor/fusion-framework-cli": "^
|
|
53
|
+
"@equinor/fusion-framework-cli": "^15.0.2"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"typescript": "^
|
|
56
|
+
"typescript": "^6.0.3",
|
|
57
57
|
"vitest": "^4.1.0",
|
|
58
|
-
"@equinor/fusion-framework-cli": "^
|
|
58
|
+
"@equinor/fusion-framework-cli": "^15.0.2"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "tsc -b",
|
package/src/options/options.ts
CHANGED
|
@@ -51,6 +51,11 @@ export const indexNameOption = createOption(
|
|
|
51
51
|
'Azure AI Search index name',
|
|
52
52
|
).env('FUSION_AI_INDEX_NAME');
|
|
53
53
|
|
|
54
|
+
/** `-d, --debug` | `RUNNER_DEBUG` — enable verbose logging */
|
|
55
|
+
export const debugOption = createOption('-d, --debug', 'Enable debug mode for verbose logging')
|
|
56
|
+
.env('RUNNER_DEBUG')
|
|
57
|
+
.default(false);
|
|
58
|
+
|
|
54
59
|
export default {
|
|
55
60
|
envOption,
|
|
56
61
|
tokenOption,
|
|
@@ -59,4 +64,5 @@ export default {
|
|
|
59
64
|
chatModelOption,
|
|
60
65
|
embedModelOption,
|
|
61
66
|
indexNameOption,
|
|
67
|
+
debugOption,
|
|
62
68
|
};
|
package/src/options/schema.ts
CHANGED
|
@@ -21,6 +21,7 @@ export const AiOptionsSchema = z
|
|
|
21
21
|
chatModel: z.string().min(1).optional(),
|
|
22
22
|
embedModel: z.string().min(1).optional(),
|
|
23
23
|
indexName: z.string().min(1).optional(),
|
|
24
|
+
debug: z.coerce.boolean().default(false),
|
|
24
25
|
})
|
|
25
26
|
.describe('Base Fusion AI command options');
|
|
26
27
|
|
package/src/options/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type Command, InvalidOptionArgumentError } from 'commander';
|
|
|
2
2
|
import {
|
|
3
3
|
chatModelOption,
|
|
4
4
|
clientIdOption,
|
|
5
|
+
debugOption,
|
|
5
6
|
embedModelOption,
|
|
6
7
|
envOption,
|
|
7
8
|
indexNameOption,
|
|
@@ -38,6 +39,7 @@ export const withOptions = (
|
|
|
38
39
|
command.addOption(tokenOption);
|
|
39
40
|
command.addOption(tenantIdOption);
|
|
40
41
|
command.addOption(clientIdOption);
|
|
42
|
+
command.addOption(debugOption);
|
|
41
43
|
|
|
42
44
|
if (args?.includeChat) command.addOption(chatModelOption);
|
|
43
45
|
if (args?.includeEmbedding) command.addOption(embedModelOption);
|
package/src/setup-framework.ts
CHANGED
|
@@ -5,59 +5,42 @@ import { initializeFramework, FusionEnv } from '@equinor/fusion-framework-cli/bi
|
|
|
5
5
|
import type { FusionFrameworkSettings, FusionFramework } from '@equinor/fusion-framework-cli/bin';
|
|
6
6
|
import type { AiOptions } from './options/index.js';
|
|
7
7
|
|
|
8
|
-
import { execFileSync } from 'node:child_process';
|
|
9
|
-
|
|
10
8
|
/** Initialized framework instance with the AI module. */
|
|
11
9
|
export type FrameworkInstance = FusionFramework<[AIModule]>;
|
|
12
10
|
|
|
13
|
-
/**
|
|
14
|
-
* Check whether an error (possibly wrapped in a cause chain) is an
|
|
15
|
-
* authentication-related failure that may be recoverable via interactive login.
|
|
16
|
-
*
|
|
17
|
-
* @internal
|
|
18
|
-
*/
|
|
19
|
-
const isAuthError = (error: unknown): boolean => {
|
|
20
|
-
let current: unknown = error;
|
|
21
|
-
while (current) {
|
|
22
|
-
if (current instanceof Error) {
|
|
23
|
-
if (
|
|
24
|
-
current.name === 'NoAccountsError' ||
|
|
25
|
-
current.name === 'SilentTokenAcquisitionError' ||
|
|
26
|
-
current.message.includes('No accounts found')
|
|
27
|
-
) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
current = (current as { cause?: unknown }).cause;
|
|
32
|
-
}
|
|
33
|
-
return false;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
11
|
/**
|
|
37
12
|
* Creates a Fusion Framework instance with the AI module enabled.
|
|
38
13
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
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.
|
|
43
18
|
*
|
|
44
19
|
* @param options - CLI options resolved by {@link withOptions}.
|
|
45
20
|
* @returns A fully initialised framework instance with the AI module.
|
|
46
21
|
* @throws {Error} When authentication fails after the interactive retry.
|
|
47
22
|
*/
|
|
48
23
|
export const setupFramework = async (options: AiOptions): Promise<FusionFramework<[AIModule]>> => {
|
|
49
|
-
|
|
24
|
+
const debug = options.debug ?? false;
|
|
25
|
+
|
|
26
|
+
// Auth strategy:
|
|
27
|
+
// 1. Explicit token (--token / FUSION_TOKEN) → direct token passthrough
|
|
28
|
+
// 2. Everything else → Azure Identity (DefaultAzureCredential)
|
|
50
29
|
const auth: FusionFrameworkSettings['auth'] = options.token
|
|
51
30
|
? { token: options.token }
|
|
52
|
-
: {
|
|
53
|
-
tenantId: options.tenantId ?? '3aa4a235-b6e2-48d5-9195-7fcf05b459b0',
|
|
54
|
-
clientId: options.clientId ?? 'a318b8e1-0295-4e17-98d5-35f67dfeba14',
|
|
55
|
-
};
|
|
31
|
+
: { defaultCredential: true };
|
|
56
32
|
|
|
57
33
|
const env = (options.env as FusionEnv) ?? FusionEnv.ContinuesIntegration;
|
|
58
34
|
|
|
35
|
+
if (debug) {
|
|
36
|
+
console.debug('[debug] Environment:', env);
|
|
37
|
+
console.debug('[debug] Auth mode:', options.token ? 'static-token' : 'azure-identity');
|
|
38
|
+
}
|
|
39
|
+
|
|
59
40
|
/** Initialise the framework, resolve the AI service, and pre-cache tokens. */
|
|
60
41
|
const initAndSetup = async (): Promise<FusionFramework<[AIModule]>> => {
|
|
42
|
+
if (debug) console.debug('[debug] Initializing framework with AI module…');
|
|
43
|
+
|
|
61
44
|
const framework = await initializeFramework<[AIModule]>({ env, auth }, (configurator) => {
|
|
62
45
|
enableAI(configurator);
|
|
63
46
|
});
|
|
@@ -67,36 +50,22 @@ export const setupFramework = async (options: AiOptions): Promise<FusionFramewor
|
|
|
67
50
|
const service = await framework.serviceDiscovery.resolveService('ai');
|
|
68
51
|
const scopes = service.scopes ?? service.defaultScopes ?? [];
|
|
69
52
|
|
|
53
|
+
if (debug) {
|
|
54
|
+
console.debug('[debug] AI service URL:', service.uri);
|
|
55
|
+
console.debug('[debug] AI service scopes:', scopes);
|
|
56
|
+
}
|
|
57
|
+
|
|
70
58
|
// Pre-cache a token for the AI service scopes so strategy callbacks
|
|
71
59
|
// don't attempt (and fail) a silent acquisition later.
|
|
72
60
|
const token = await framework.auth.acquireAccessToken({ request: { scopes } });
|
|
73
61
|
if (!token) throw new Error('Failed to acquire access token for the AI service.');
|
|
74
62
|
|
|
63
|
+
if (debug) console.debug('[debug] Token acquired successfully');
|
|
64
|
+
|
|
75
65
|
return framework;
|
|
76
66
|
};
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
return await initAndSetup();
|
|
80
|
-
} catch (error: unknown) {
|
|
81
|
-
// If the failure is auth-related and we're not using a static token,
|
|
82
|
-
// spawn the CLI's own `auth login` (starts local server + browser)
|
|
83
|
-
// and retry the full init sequence.
|
|
84
|
-
if (!isAuthError(error) || options.token) throw error;
|
|
85
|
-
|
|
86
|
-
const cliEntry = process.argv[1];
|
|
87
|
-
if (!cliEntry) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
'Failed to acquire access token and could not determine CLI path for interactive login.',
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
console.log('No cached credentials — launching interactive login…');
|
|
94
|
-
execFileSync(process.execPath, [cliEntry, 'auth', 'login'], {
|
|
95
|
-
stdio: 'inherit',
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
return await initAndSetup();
|
|
99
|
-
}
|
|
68
|
+
return await initAndSetup();
|
|
100
69
|
};
|
|
101
70
|
|
|
102
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.1';
|