@aigne/aigne-hub 0.4.7 → 0.4.9

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/lib/cjs/blocklet-aigne-hub-model.js +4 -3
  3. package/lib/cjs/cli-aigne-hub-model.js +1 -1
  4. package/lib/cjs/index.d.ts +5 -1
  5. package/lib/cjs/index.js +8 -3
  6. package/lib/cjs/util/constants.d.ts +13 -0
  7. package/lib/cjs/util/constants.js +29 -0
  8. package/lib/cjs/util/credential.d.ts +24 -0
  9. package/lib/cjs/util/credential.js +223 -0
  10. package/lib/cjs/util/crypto.d.ts +4 -0
  11. package/lib/cjs/util/crypto.js +19 -0
  12. package/lib/cjs/util/model.d.ts +12 -0
  13. package/lib/cjs/util/model.js +201 -0
  14. package/lib/cjs/util/type.d.ts +58 -0
  15. package/lib/cjs/util/type.js +2 -0
  16. package/lib/dts/index.d.ts +5 -1
  17. package/lib/dts/util/constants.d.ts +13 -0
  18. package/lib/dts/util/credential.d.ts +24 -0
  19. package/lib/dts/util/crypto.d.ts +4 -0
  20. package/lib/dts/util/model.d.ts +12 -0
  21. package/lib/dts/util/type.d.ts +58 -0
  22. package/lib/esm/blocklet-aigne-hub-model.js +2 -1
  23. package/lib/esm/cli-aigne-hub-model.js +1 -1
  24. package/lib/esm/index.d.ts +5 -1
  25. package/lib/esm/index.js +7 -2
  26. package/lib/esm/util/constants.d.ts +13 -0
  27. package/lib/esm/util/constants.js +15 -0
  28. package/lib/esm/util/credential.d.ts +24 -0
  29. package/lib/esm/util/credential.js +211 -0
  30. package/lib/esm/util/crypto.d.ts +4 -0
  31. package/lib/esm/util/crypto.js +9 -0
  32. package/lib/esm/util/model.d.ts +12 -0
  33. package/lib/esm/{constants.js → util/model.js} +91 -18
  34. package/lib/esm/util/type.d.ts +58 -0
  35. package/lib/esm/util/type.js +1 -0
  36. package/package.json +22 -15
  37. package/lib/cjs/constants.d.ts +0 -28
  38. package/lib/cjs/constants.js +0 -123
  39. package/lib/dts/constants.d.ts +0 -28
  40. package/lib/esm/constants.d.ts +0 -28
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.9](https://github.com/AIGNE-io/aigne-framework/compare/aigne-hub-v0.4.8...aigne-hub-v0.4.9) (2025-08-12)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **core:** examples cases that failed when using aigne-hub ([#337](https://github.com/AIGNE-io/aigne-framework/issues/337)) ([0d4a31c](https://github.com/AIGNE-io/aigne-framework/commit/0d4a31c24d9e7d26f00d1accb80719d9ad79a4c6))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @aigne/anthropic bumped to 0.11.0
16
+ * @aigne/bedrock bumped to 0.9.0
17
+ * @aigne/core bumped to 1.49.0
18
+ * @aigne/deepseek bumped to 0.7.18
19
+ * @aigne/default-memory bumped to 1.1.0
20
+ * @aigne/gemini bumped to 0.9.0
21
+ * @aigne/ollama bumped to 0.7.18
22
+ * @aigne/open-router bumped to 0.7.18
23
+ * @aigne/openai bumped to 0.11.0
24
+ * @aigne/platform-helpers bumped to 0.6.1
25
+ * @aigne/transport bumped to 0.13.0
26
+ * @aigne/xai bumped to 0.7.18
27
+ * devDependencies
28
+ * @aigne/openai bumped to 0.11.0
29
+ * @aigne/test-utils bumped to 0.5.26
30
+
31
+ ## [0.4.8](https://github.com/AIGNE-io/aigne-framework/compare/aigne-hub-v0.4.7...aigne-hub-v0.4.8) (2025-08-12)
32
+
33
+
34
+ ### Dependencies
35
+
36
+ * The following workspace dependencies were updated
37
+ * dependencies
38
+ * @aigne/anthropic bumped to 0.10.13
39
+ * @aigne/bedrock bumped to 0.8.17
40
+ * @aigne/core bumped to 1.48.0
41
+ * @aigne/deepseek bumped to 0.7.17
42
+ * @aigne/default-memory bumped to 1.0.17
43
+ * @aigne/gemini bumped to 0.8.17
44
+ * @aigne/ollama bumped to 0.7.17
45
+ * @aigne/open-router bumped to 0.7.17
46
+ * @aigne/openai bumped to 0.10.17
47
+ * @aigne/transport bumped to 0.12.5
48
+ * @aigne/xai bumped to 0.7.17
49
+ * devDependencies
50
+ * @aigne/openai bumped to 0.10.17
51
+ * @aigne/test-utils bumped to 0.5.25
52
+
3
53
  ## [0.4.7](https://github.com/AIGNE-io/aigne-framework/compare/aigne-hub-v0.4.6...aigne-hub-v0.4.7) (2025-08-11)
4
54
 
5
55
 
@@ -2,17 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BlockletAIGNEHubChatModel = void 0;
4
4
  const core_1 = require("@aigne/core");
5
- const constants_js_1 = require("./constants.js");
5
+ const constants_js_1 = require("./util/constants.js");
6
+ const model_js_1 = require("./util/model.js");
6
7
  class BlockletAIGNEHubChatModel extends core_1.ChatModel {
7
8
  options;
8
9
  client;
9
10
  constructor(options) {
10
11
  super();
11
12
  this.options = options;
12
- const models = (0, constants_js_1.availableModels)();
13
+ const models = (0, model_js_1.availableModels)();
13
14
  const rawProvider = process.env.BLOCKLET_AIGNE_API_PROVIDER ?? "";
14
15
  const providerKey = rawProvider.toLowerCase().replace(/-/g, "");
15
- const modelEntry = (0, constants_js_1.findModel)(models, providerKey);
16
+ const modelEntry = (0, model_js_1.findModel)(models, providerKey);
16
17
  if (!modelEntry) {
17
18
  const available = models.map((m) => m.name).join(", ");
18
19
  throw new Error(`Unsupported model provider: ${rawProvider} ${process.env.BLOCKLET_AIGNE_API_MODEL}. Available providers: ${available}`);
@@ -6,7 +6,7 @@ const type_utils_js_1 = require("@aigne/core/utils/type-utils.js");
6
6
  const base_client_js_1 = require("@aigne/transport/http-client/base-client.js");
7
7
  const ufo_1 = require("ufo");
8
8
  const zod_1 = require("zod");
9
- const constants_js_1 = require("./constants.js");
9
+ const constants_js_1 = require("./util/constants.js");
10
10
  const DEFAULT_CHAT_MODEL = "openai/gpt-4o";
11
11
  const aigneHubChatModelOptionsSchema = zod_1.z.object({
12
12
  url: zod_1.z.string().optional(),
@@ -2,7 +2,11 @@ import { type AgentInvokeOptions, type AgentProcessResult, ChatModel, type ChatM
2
2
  import type { PromiseOrValue } from "@aigne/core/utils/type-utils.js";
3
3
  import { type HubChatModelOptions } from "./blocklet-aigne-hub-model.js";
4
4
  import { type AIGNEHubChatModelOptions } from "./cli-aigne-hub-model.js";
5
- export * from "./constants.js";
5
+ export * from "./util/constants.js";
6
+ export * from "./util/credential.js";
7
+ export * from "./util/crypto.js";
8
+ export * from "./util/model.js";
9
+ export * from "./util/type.js";
6
10
  export declare class AIGNEHubChatModel extends ChatModel {
7
11
  options: HubChatModelOptions;
8
12
  private client;
package/lib/cjs/index.js CHANGED
@@ -18,8 +18,13 @@ exports.AIGNEHubChatModel = void 0;
18
18
  const core_1 = require("@aigne/core");
19
19
  const blocklet_aigne_hub_model_js_1 = require("./blocklet-aigne-hub-model.js");
20
20
  const cli_aigne_hub_model_js_1 = require("./cli-aigne-hub-model.js");
21
- const constants_js_1 = require("./constants.js");
22
- __exportStar(require("./constants.js"), exports);
21
+ const constants_js_1 = require("./util/constants.js");
22
+ const credential_js_1 = require("./util/credential.js");
23
+ __exportStar(require("./util/constants.js"), exports);
24
+ __exportStar(require("./util/credential.js"), exports);
25
+ __exportStar(require("./util/crypto.js"), exports);
26
+ __exportStar(require("./util/model.js"), exports);
27
+ __exportStar(require("./util/type.js"), exports);
23
28
  class AIGNEHubChatModel extends core_1.ChatModel {
24
29
  options;
25
30
  client;
@@ -27,7 +32,7 @@ class AIGNEHubChatModel extends core_1.ChatModel {
27
32
  const u = process.env.BLOCKLET_AIGNE_API_URL ?? process.env.AIGNE_HUB_API_URL ?? constants_js_1.AIGNE_HUB_URL;
28
33
  let url = options.url ?? u;
29
34
  if ((process.env.BLOCKLET_AIGNE_API_PROVIDER || "").toLocaleLowerCase().includes("aignehub")) {
30
- url = await (0, constants_js_1.getAIGNEHubMountPoint)(url);
35
+ url = await (0, credential_js_1.getAIGNEHubMountPoint)(url);
31
36
  }
32
37
  return new AIGNEHubChatModel({ ...options, url });
33
38
  }
@@ -0,0 +1,13 @@
1
+ declare const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
2
+ declare const ACCESS_KEY_PREFIX = "/api/access-key";
3
+ declare const ACCESS_KEY_SESSION_API = "/api/access-key/session";
4
+ declare const AIGNE_HUB_DID = "z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ";
5
+ declare const AGENT_HUB_PROVIDER = "aignehub";
6
+ declare const AIGNE_HUB_URL = "https://hub.aigne.io/";
7
+ declare const DEFAULT_AIGNE_HUB_PROVIDER_MODEL = "aignehub:openai/gpt-5-mini";
8
+ declare const DEFAULT_MODEL_PROVIDER = "openai";
9
+ declare const isTest: string | boolean;
10
+ declare const TEST_AIGNE_ENV_FILE: string;
11
+ declare const PROD_AIGNE_ENV_FILE: string;
12
+ declare const AIGNE_ENV_FILE: string;
13
+ export { DEFAULT_AIGNE_HUB_PROVIDER_MODEL, DEFAULT_MODEL_PROVIDER, AIGNE_HUB_DID, AIGNE_HUB_URL, isTest, WELLKNOWN_SERVICE_PATH_PREFIX, ACCESS_KEY_PREFIX, ACCESS_KEY_SESSION_API, AGENT_HUB_PROVIDER, TEST_AIGNE_ENV_FILE, PROD_AIGNE_ENV_FILE, AIGNE_ENV_FILE, };
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AIGNE_ENV_FILE = exports.PROD_AIGNE_ENV_FILE = exports.TEST_AIGNE_ENV_FILE = exports.AGENT_HUB_PROVIDER = exports.ACCESS_KEY_SESSION_API = exports.ACCESS_KEY_PREFIX = exports.WELLKNOWN_SERVICE_PATH_PREFIX = exports.isTest = exports.AIGNE_HUB_URL = exports.AIGNE_HUB_DID = exports.DEFAULT_MODEL_PROVIDER = exports.DEFAULT_AIGNE_HUB_PROVIDER_MODEL = void 0;
4
+ const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
5
+ const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
6
+ exports.WELLKNOWN_SERVICE_PATH_PREFIX = WELLKNOWN_SERVICE_PATH_PREFIX;
7
+ const ACCESS_KEY_PREFIX = "/api/access-key";
8
+ exports.ACCESS_KEY_PREFIX = ACCESS_KEY_PREFIX;
9
+ const ACCESS_KEY_SESSION_API = `${ACCESS_KEY_PREFIX}/session`;
10
+ exports.ACCESS_KEY_SESSION_API = ACCESS_KEY_SESSION_API;
11
+ const AIGNE_HUB_DID = "z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ";
12
+ exports.AIGNE_HUB_DID = AIGNE_HUB_DID;
13
+ const AGENT_HUB_PROVIDER = "aignehub";
14
+ exports.AGENT_HUB_PROVIDER = AGENT_HUB_PROVIDER;
15
+ const AIGNE_HUB_URL = "https://hub.aigne.io/";
16
+ exports.AIGNE_HUB_URL = AIGNE_HUB_URL;
17
+ const DEFAULT_AIGNE_HUB_MODEL = "openai/gpt-5-mini";
18
+ const DEFAULT_AIGNE_HUB_PROVIDER_MODEL = `${AGENT_HUB_PROVIDER}:${DEFAULT_AIGNE_HUB_MODEL}`;
19
+ exports.DEFAULT_AIGNE_HUB_PROVIDER_MODEL = DEFAULT_AIGNE_HUB_PROVIDER_MODEL;
20
+ const DEFAULT_MODEL_PROVIDER = "openai";
21
+ exports.DEFAULT_MODEL_PROVIDER = DEFAULT_MODEL_PROVIDER;
22
+ const isTest = process.env.CI || process.env.NODE_ENV === "test";
23
+ exports.isTest = isTest;
24
+ const TEST_AIGNE_ENV_FILE = index_js_1.nodejs.path.join(index_js_1.nodejs.os.homedir(), ".aigne", "test-aigne-hub-connected.yaml");
25
+ exports.TEST_AIGNE_ENV_FILE = TEST_AIGNE_ENV_FILE;
26
+ const PROD_AIGNE_ENV_FILE = index_js_1.nodejs.path.join(index_js_1.nodejs.os.homedir(), ".aigne", "aigne-hub-connected.yaml");
27
+ exports.PROD_AIGNE_ENV_FILE = PROD_AIGNE_ENV_FILE;
28
+ const AIGNE_ENV_FILE = isTest ? TEST_AIGNE_ENV_FILE : PROD_AIGNE_ENV_FILE;
29
+ exports.AIGNE_ENV_FILE = AIGNE_ENV_FILE;
@@ -0,0 +1,24 @@
1
+ import type { CreateConnectOptions, FetchResult, LoadCredentialOptions } from "./type.js";
2
+ export declare const fetchConfigs: ({ connectUrl, sessionId, fetchInterval, fetchTimeout, }: {
3
+ connectUrl: string;
4
+ sessionId: string;
5
+ fetchInterval: number;
6
+ fetchTimeout: number;
7
+ }) => Promise<any>;
8
+ export declare function createConnect({ connectUrl, openPage, fetchInterval, retry, source, connectAction, wrapSpinner, closeOnSuccess, intervalFetchConfig, appName, appLogo, }: CreateConnectOptions): Promise<FetchResult>;
9
+ export declare function getAIGNEHubMountPoint(url: string): Promise<string>;
10
+ export declare function connectToAIGNEHub(url: string): Promise<{
11
+ apiKey: string;
12
+ url: string;
13
+ } | {
14
+ apiKey: undefined;
15
+ url: undefined;
16
+ }>;
17
+ export declare const checkConnectionStatus: (host: string) => Promise<{
18
+ apiKey: any;
19
+ url: string;
20
+ }>;
21
+ export declare function loadCredential(options?: LoadCredentialOptions): Promise<{
22
+ apiKey?: string;
23
+ url?: string;
24
+ } | undefined>;
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.checkConnectionStatus = exports.fetchConfigs = void 0;
7
+ exports.createConnect = createConnect;
8
+ exports.getAIGNEHubMountPoint = getAIGNEHubMountPoint;
9
+ exports.connectToAIGNEHub = connectToAIGNEHub;
10
+ exports.loadCredential = loadCredential;
11
+ const logger_js_1 = require("@aigne/core/utils/logger.js");
12
+ const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
13
+ const inquirer_1 = __importDefault(require("inquirer"));
14
+ const open_1 = __importDefault(require("open"));
15
+ const p_wait_for_1 = __importDefault(require("p-wait-for"));
16
+ const ufo_1 = require("ufo");
17
+ const yaml_1 = require("yaml");
18
+ const constants_js_1 = require("./constants.js");
19
+ const crypto_js_1 = require("./crypto.js");
20
+ const request = async (config) => {
21
+ const headers = {};
22
+ if (config.requestCount !== undefined) {
23
+ headers["X-Request-Count"] = config.requestCount.toString();
24
+ }
25
+ const response = await fetch(config.url, { method: config.method || "GET", headers });
26
+ if (!response.ok)
27
+ throw new Error(`HTTP error! status: ${response.status}`);
28
+ const data = await response.json();
29
+ return { data };
30
+ };
31
+ const fetchConfigs = async ({ connectUrl, sessionId, fetchInterval, fetchTimeout, }) => {
32
+ const sessionURL = (0, ufo_1.withQuery)((0, ufo_1.joinURL)(connectUrl, constants_js_1.ACCESS_KEY_SESSION_API), { sid: sessionId });
33
+ let requestCount = 0;
34
+ const condition = async () => {
35
+ const { data: session } = await request({ url: sessionURL, requestCount });
36
+ requestCount++;
37
+ return Boolean(session.accessKeyId && session.accessKeySecret);
38
+ };
39
+ await (0, p_wait_for_1.default)(condition, { interval: fetchInterval, timeout: fetchTimeout });
40
+ const { data: session } = await request({ url: sessionURL, requestCount });
41
+ await request({ url: sessionURL, method: "DELETE" });
42
+ return {
43
+ ...session,
44
+ accessKeyId: session.accessKeyId,
45
+ accessKeySecret: (0, crypto_js_1.decrypt)(session.accessKeySecret, session.accessKeyId, session.challenge),
46
+ };
47
+ };
48
+ exports.fetchConfigs = fetchConfigs;
49
+ function baseWrapSpinner(_, waiting) {
50
+ return Promise.resolve(waiting());
51
+ }
52
+ async function createConnect({ connectUrl, openPage, fetchInterval = 3 * 1000, retry = 1500, source = "Blocklet CLI", connectAction = "connect-cli", wrapSpinner = baseWrapSpinner, closeOnSuccess, intervalFetchConfig, appName = "AIGNE CLI", appLogo = "https://www.aigne.io/favicon.ico?imageFilter=resize&w=32", }) {
53
+ const startSessionURL = (0, ufo_1.joinURL)(connectUrl, constants_js_1.ACCESS_KEY_SESSION_API);
54
+ const { data: session } = await request({ url: startSessionURL, method: "POST" });
55
+ const token = session.id;
56
+ const pageUrl = (0, ufo_1.withQuery)((0, ufo_1.joinURL)(connectUrl, connectAction), {
57
+ __token__: (0, crypto_js_1.encodeEncryptionKey)(token),
58
+ source,
59
+ closeOnSuccess,
60
+ cli: true,
61
+ appName: ` ${appName}`,
62
+ appLogo,
63
+ });
64
+ openPage?.(pageUrl);
65
+ return await wrapSpinner(`Waiting for connection: ${connectUrl}`, async () => {
66
+ const checkAuthorizeStatus = intervalFetchConfig ?? exports.fetchConfigs;
67
+ const authorizeStatus = await checkAuthorizeStatus({
68
+ connectUrl,
69
+ sessionId: token,
70
+ fetchTimeout: retry * fetchInterval,
71
+ fetchInterval: retry,
72
+ });
73
+ return authorizeStatus;
74
+ });
75
+ }
76
+ async function getAIGNEHubMountPoint(url) {
77
+ const { origin } = new URL(url);
78
+ const BLOCKLET_JSON_PATH = "__blocklet__.js?type=json";
79
+ const blockletInfo = await fetch((0, ufo_1.joinURL)(origin, BLOCKLET_JSON_PATH));
80
+ const blocklet = await blockletInfo.json();
81
+ const aigneHubMount = (blocklet?.componentMountPoints || []).find((m) => m.did === constants_js_1.AIGNE_HUB_DID);
82
+ return (0, ufo_1.joinURL)(origin, aigneHubMount?.mountPoint || "");
83
+ }
84
+ async function connectToAIGNEHub(url) {
85
+ const { origin, host } = new URL(url);
86
+ const connectUrl = (0, ufo_1.joinURL)(origin, constants_js_1.WELLKNOWN_SERVICE_PATH_PREFIX);
87
+ const urlWithAIGNEHubMountPoint = await getAIGNEHubMountPoint(url);
88
+ try {
89
+ const openFn = constants_js_1.isTest ? () => { } : open_1.default;
90
+ const result = await createConnect({
91
+ connectUrl: connectUrl,
92
+ connectAction: "gen-simple-access-key",
93
+ source: `@aigne/cli connect to AIGNE hub`,
94
+ closeOnSuccess: true,
95
+ openPage: (pageUrl) => openFn(pageUrl),
96
+ });
97
+ const accessKeyOptions = {
98
+ apiKey: result.accessKeySecret,
99
+ url: urlWithAIGNEHubMountPoint,
100
+ };
101
+ // After redirection, write the AIGNE Hub access token
102
+ const aigneDir = index_js_1.nodejs.path.join(index_js_1.nodejs.os.homedir(), ".aigne");
103
+ if (!index_js_1.nodejs.fsSync.existsSync(aigneDir)) {
104
+ index_js_1.nodejs.fsSync.mkdirSync(aigneDir, { recursive: true });
105
+ }
106
+ const envs = (0, yaml_1.parse)(await index_js_1.nodejs.fs.readFile(constants_js_1.AIGNE_ENV_FILE, "utf8").catch(() => (0, yaml_1.stringify)({})));
107
+ await index_js_1.nodejs.fs.writeFile(constants_js_1.AIGNE_ENV_FILE, (0, yaml_1.stringify)({
108
+ ...envs,
109
+ [host]: {
110
+ AIGNE_HUB_API_KEY: accessKeyOptions.apiKey,
111
+ AIGNE_HUB_API_URL: accessKeyOptions.url,
112
+ },
113
+ default: {
114
+ AIGNE_HUB_API_URL: accessKeyOptions.url,
115
+ },
116
+ }));
117
+ return accessKeyOptions;
118
+ }
119
+ catch (error) {
120
+ logger_js_1.logger.error("Failed to connect to AIGNE Hub", error.message);
121
+ return { apiKey: undefined, url: undefined };
122
+ }
123
+ }
124
+ const checkConnectionStatus = async (host) => {
125
+ // aigne-hub access token
126
+ if (!index_js_1.nodejs.fsSync.existsSync(constants_js_1.AIGNE_ENV_FILE)) {
127
+ throw new Error("AIGNE_HUB_API_KEY file not found, need to login first");
128
+ }
129
+ const data = await index_js_1.nodejs.fs.readFile(constants_js_1.AIGNE_ENV_FILE, "utf8");
130
+ if (!data.includes("AIGNE_HUB_API_KEY")) {
131
+ throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
132
+ }
133
+ const envs = (0, yaml_1.parse)(data);
134
+ if (!envs[host]) {
135
+ throw new Error("AIGNE_HUB_API_KEY host not found, need to login first");
136
+ }
137
+ const env = envs[host];
138
+ if (!env.AIGNE_HUB_API_KEY) {
139
+ throw new Error("AIGNE_HUB_API_KEY key not found, need to login first");
140
+ }
141
+ return {
142
+ apiKey: env.AIGNE_HUB_API_KEY,
143
+ url: (0, ufo_1.joinURL)(env.AIGNE_HUB_API_URL),
144
+ };
145
+ };
146
+ exports.checkConnectionStatus = checkConnectionStatus;
147
+ async function loadCredential(options) {
148
+ const isBlocklet = process.env.BLOCKLET_AIGNE_API_URL && process.env.BLOCKLET_AIGNE_API_PROVIDER;
149
+ if (isBlocklet)
150
+ return undefined;
151
+ const aigneDir = index_js_1.nodejs.path.join(index_js_1.nodejs.os.homedir(), ".aigne");
152
+ if (!index_js_1.nodejs.fsSync.existsSync(aigneDir)) {
153
+ index_js_1.nodejs.fsSync.mkdirSync(aigneDir, { recursive: true });
154
+ }
155
+ const envs = (0, yaml_1.parse)(await index_js_1.nodejs.fs.readFile(constants_js_1.AIGNE_ENV_FILE, "utf8").catch(() => (0, yaml_1.stringify)({})));
156
+ const inquirerPrompt = (options?.inquirerPromptFn ?? inquirer_1.default.prompt);
157
+ const configUrl = options?.aigneHubUrl || process.env.AIGNE_HUB_API_URL;
158
+ const AIGNE_HUB_URL = configUrl || envs?.default?.AIGNE_HUB_API_URL || constants_js_1.AIGNE_HUB_URL;
159
+ const connectUrl = (0, ufo_1.joinURL)(new URL(AIGNE_HUB_URL).origin, constants_js_1.WELLKNOWN_SERVICE_PATH_PREFIX);
160
+ const { host } = new URL(AIGNE_HUB_URL);
161
+ const modelName = options?.model || "";
162
+ const isAIGNEHubModel = (modelName.toLocaleLowerCase() || "").includes(constants_js_1.AGENT_HUB_PROVIDER);
163
+ let credential = {};
164
+ if (isAIGNEHubModel) {
165
+ try {
166
+ credential = await (0, exports.checkConnectionStatus)(host);
167
+ }
168
+ catch (error) {
169
+ if (error instanceof Error && error.message.includes("login first")) {
170
+ let aigneHubUrl = connectUrl;
171
+ if (!configUrl) {
172
+ const { subscribe } = await inquirerPrompt({
173
+ type: "list",
174
+ name: "subscribe",
175
+ message: "No LLM API Keys or AIGNE Hub connections found. How would you like to proceed?",
176
+ choices: [
177
+ {
178
+ name: "Connect to the Arcblock official AIGNE Hub (recommended, free credits for new users)",
179
+ value: "official",
180
+ },
181
+ connectUrl.includes(constants_js_1.AIGNE_HUB_URL)
182
+ ? {
183
+ name: "Connect to your own AIGNE Hub instance (self-hosted)",
184
+ value: "custom",
185
+ }
186
+ : null,
187
+ {
188
+ name: "Exit and configure my own LLM API Keys",
189
+ value: "manual",
190
+ },
191
+ ].filter(Boolean),
192
+ default: "official",
193
+ });
194
+ if (subscribe === "custom") {
195
+ const { customUrl } = await inquirerPrompt({
196
+ type: "input",
197
+ name: "customUrl",
198
+ message: "Enter the URL of your AIGNE Hub:",
199
+ validate(input) {
200
+ try {
201
+ const url = new URL(input);
202
+ return url.protocol.startsWith("http")
203
+ ? true
204
+ : "Must be a valid URL with http or https";
205
+ }
206
+ catch {
207
+ return "Invalid URL";
208
+ }
209
+ },
210
+ });
211
+ aigneHubUrl = customUrl;
212
+ }
213
+ else if (subscribe === "manual") {
214
+ console.log("You chose to configure your own LLM API Keys. Exiting...");
215
+ process.exit(0);
216
+ }
217
+ }
218
+ credential = await connectToAIGNEHub(aigneHubUrl);
219
+ }
220
+ }
221
+ }
222
+ return credential;
223
+ }
@@ -0,0 +1,4 @@
1
+ export declare const decrypt: (m: string, s: string, i: string) => string;
2
+ export declare const encrypt: (m: string, s: string, i: string) => string;
3
+ export declare const encodeEncryptionKey: (key: string) => string;
4
+ export declare const decodeEncryptionKey: (str: string) => Uint8Array<ArrayBuffer>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.decodeEncryptionKey = exports.encodeEncryptionKey = exports.encrypt = exports.decrypt = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const aes_legacy_js_1 = require("@ocap/mcrypto/lib/crypter/aes-legacy.js");
9
+ const aes = new aes_legacy_js_1.AesCrypter();
10
+ const decrypt = (m, s, i) => aes.decrypt(m, node_crypto_1.default.pbkdf2Sync(i, s, 256, 32, "sha512").toString("hex"));
11
+ exports.decrypt = decrypt;
12
+ const encrypt = (m, s, i) => aes.encrypt(m, node_crypto_1.default.pbkdf2Sync(i, s, 256, 32, "sha512").toString("hex"));
13
+ exports.encrypt = encrypt;
14
+ const escapeFn = (str) => str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
15
+ const unescapeFn = (str) => (str + "===".slice((str.length + 3) % 4)).replace(/-/g, "+").replace(/_/g, "/");
16
+ const encodeEncryptionKey = (key) => escapeFn(Buffer.from(key).toString("base64"));
17
+ exports.encodeEncryptionKey = encodeEncryptionKey;
18
+ const decodeEncryptionKey = (str) => new Uint8Array(Buffer.from(unescapeFn(str), "base64"));
19
+ exports.decodeEncryptionKey = decodeEncryptionKey;
@@ -0,0 +1,12 @@
1
+ import type { ChatModel, ChatModelOptions } from "@aigne/core/agents/chat-model.js";
2
+ import type inquirer from "inquirer";
3
+ import type { LoadableModel, LoadCredentialOptions, Model } from "./type.js";
4
+ export declare function availableModels(): LoadableModel[];
5
+ export declare function findModel(models: LoadableModel[], provider: string): LoadableModel | undefined;
6
+ export declare const parseModelOption: (model?: string) => {
7
+ provider: string | undefined;
8
+ name: string | undefined;
9
+ };
10
+ export declare const formatModelName: (model: string, inquirerPrompt: typeof inquirer.prompt) => Promise<string>;
11
+ export declare function maskApiKey(apiKey?: string): string | undefined;
12
+ export declare function loadModel(model?: Model, modelOptions?: ChatModelOptions, options?: LoadCredentialOptions): Promise<ChatModel | undefined>;
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatModelName = exports.parseModelOption = void 0;
7
+ exports.availableModels = availableModels;
8
+ exports.findModel = findModel;
9
+ exports.maskApiKey = maskApiKey;
10
+ exports.loadModel = loadModel;
11
+ const anthropic_1 = require("@aigne/anthropic");
12
+ const bedrock_1 = require("@aigne/bedrock");
13
+ const deepseek_1 = require("@aigne/deepseek");
14
+ const gemini_1 = require("@aigne/gemini");
15
+ const ollama_1 = require("@aigne/ollama");
16
+ const open_router_1 = require("@aigne/open-router");
17
+ const openai_1 = require("@aigne/openai");
18
+ const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
19
+ const xai_1 = require("@aigne/xai");
20
+ const node_http_handler_1 = require("@smithy/node-http-handler");
21
+ const boxen_1 = __importDefault(require("boxen"));
22
+ const chalk_1 = __importDefault(require("chalk"));
23
+ const https_proxy_agent_1 = require("https-proxy-agent");
24
+ const index_js_2 = require("../index.js");
25
+ const constants_js_1 = require("./constants.js");
26
+ const credential_js_1 = require("./credential.js");
27
+ const { MODEL_PROVIDER, MODEL_NAME } = index_js_1.nodejs.env;
28
+ function availableModels() {
29
+ const proxy = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy", "ALL_PROXY", "all_proxy"]
30
+ .map((i) => process.env[i])
31
+ .filter(Boolean)[0];
32
+ const httpAgent = proxy ? new https_proxy_agent_1.HttpsProxyAgent(proxy) : undefined;
33
+ const clientOptions = {
34
+ fetchOptions: {
35
+ // @ts-ignore
36
+ agent: httpAgent,
37
+ },
38
+ };
39
+ return [
40
+ {
41
+ name: openai_1.OpenAIChatModel.name,
42
+ apiKeyEnvName: "OPENAI_API_KEY",
43
+ create: (params) => new openai_1.OpenAIChatModel({ ...params, clientOptions }),
44
+ },
45
+ {
46
+ name: anthropic_1.AnthropicChatModel.name,
47
+ apiKeyEnvName: "ANTHROPIC_API_KEY",
48
+ create: (params) => new anthropic_1.AnthropicChatModel({ ...params, clientOptions }),
49
+ },
50
+ {
51
+ name: bedrock_1.BedrockChatModel.name,
52
+ apiKeyEnvName: "AWS_ACCESS_KEY_ID",
53
+ create: (params) => new bedrock_1.BedrockChatModel({
54
+ ...params,
55
+ clientOptions: {
56
+ requestHandler: node_http_handler_1.NodeHttpHandler.create({ httpAgent, httpsAgent: httpAgent }),
57
+ streamCollector: node_http_handler_1.streamCollector,
58
+ },
59
+ }),
60
+ },
61
+ {
62
+ name: deepseek_1.DeepSeekChatModel.name,
63
+ apiKeyEnvName: "DEEPSEEK_API_KEY",
64
+ create: (params) => new deepseek_1.DeepSeekChatModel({ ...params, clientOptions }),
65
+ },
66
+ {
67
+ name: [gemini_1.GeminiChatModel.name, "google"],
68
+ apiKeyEnvName: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
69
+ create: (params) => new gemini_1.GeminiChatModel({ ...params, clientOptions }),
70
+ },
71
+ {
72
+ name: ollama_1.OllamaChatModel.name,
73
+ apiKeyEnvName: "OLLAMA_API_KEY",
74
+ create: (params) => new ollama_1.OllamaChatModel({ ...params, clientOptions }),
75
+ },
76
+ {
77
+ name: open_router_1.OpenRouterChatModel.name,
78
+ apiKeyEnvName: "OPEN_ROUTER_API_KEY",
79
+ create: (params) => new open_router_1.OpenRouterChatModel({ ...params, clientOptions }),
80
+ },
81
+ {
82
+ name: xai_1.XAIChatModel.name,
83
+ apiKeyEnvName: "XAI_API_KEY",
84
+ create: (params) => new xai_1.XAIChatModel({ ...params, clientOptions }),
85
+ },
86
+ {
87
+ name: index_js_2.AIGNEHubChatModel.name,
88
+ apiKeyEnvName: "AIGNE_HUB_API_KEY",
89
+ create: (params) => new index_js_2.AIGNEHubChatModel({ ...params, clientOptions }),
90
+ },
91
+ ];
92
+ }
93
+ function findModel(models, provider) {
94
+ return models.find((m) => {
95
+ if (typeof m.name === "string") {
96
+ return m.name.toLowerCase().includes(provider.toLowerCase());
97
+ }
98
+ return m.name.some((n) => n.toLowerCase().includes(provider.toLowerCase()));
99
+ });
100
+ }
101
+ const parseModelOption = (model) => {
102
+ const { provider, name } = (model || process.env.MODEL)?.match(/(?<provider>[^:]*)(:(?<name>(\S+)))?/)?.groups ?? {};
103
+ return { provider, name };
104
+ };
105
+ exports.parseModelOption = parseModelOption;
106
+ const formatModelName = async (model, inquirerPrompt) => {
107
+ const models = availableModels();
108
+ if (!model)
109
+ return constants_js_1.DEFAULT_AIGNE_HUB_PROVIDER_MODEL;
110
+ const { provider, name } = (0, exports.parseModelOption)(model);
111
+ if (!provider) {
112
+ return constants_js_1.DEFAULT_AIGNE_HUB_PROVIDER_MODEL;
113
+ }
114
+ const providerName = provider.replace(/-/g, "");
115
+ if (providerName.includes(constants_js_1.AGENT_HUB_PROVIDER)) {
116
+ return model;
117
+ }
118
+ const m = findModel(models, providerName);
119
+ if (!m)
120
+ throw new Error(`Unsupported model: ${provider} ${name}`);
121
+ const apiKeyEnvName = Array.isArray(m.apiKeyEnvName) ? m.apiKeyEnvName : [m.apiKeyEnvName];
122
+ if (apiKeyEnvName.some((name) => name && process.env[name])) {
123
+ return model;
124
+ }
125
+ const result = await inquirerPrompt({
126
+ type: "list",
127
+ name: "useAigneHub",
128
+ message: `Seems no API Key configured for ${provider}/${name}, select your preferred way to continue:`,
129
+ choices: [
130
+ {
131
+ name: `Connect to AIGNE Hub to use ${name} (Recommended since free credits available)`,
132
+ value: true,
133
+ },
134
+ {
135
+ name: `Exit and bring my owner API Key by set ${apiKeyEnvName.join(", ")}`,
136
+ value: false,
137
+ },
138
+ ],
139
+ default: true,
140
+ });
141
+ if (!result.useAigneHub) {
142
+ console.log(chalk_1.default.yellow(`You can use command "export ${apiKeyEnvName[0]}=xxx" to set API Key in your shell. Or you can set environment variables in .env file.`));
143
+ process.exit(0);
144
+ }
145
+ return `${constants_js_1.AGENT_HUB_PROVIDER}:${provider}/${name}`;
146
+ };
147
+ exports.formatModelName = formatModelName;
148
+ function maskApiKey(apiKey) {
149
+ if (!apiKey || apiKey.length <= 8)
150
+ return apiKey;
151
+ const start = apiKey.slice(0, 4);
152
+ const end = apiKey.slice(-4);
153
+ return `${start}${"*".repeat(8)}${end}`;
154
+ }
155
+ function printChatModelInfoBox({ provider, model, credential, m, }) {
156
+ const lines = [
157
+ `${chalk_1.default.cyan("Provider")}: ${chalk_1.default.green(provider)}`,
158
+ `${chalk_1.default.cyan("Model")}: ${chalk_1.default.green(model)}`,
159
+ ];
160
+ if (provider.includes(constants_js_1.AGENT_HUB_PROVIDER)) {
161
+ lines.push(`${chalk_1.default.cyan("API URL")}: ${chalk_1.default.green(credential?.url || "N/A")}`, `${chalk_1.default.cyan("API Key")}: ${chalk_1.default.green(maskApiKey(credential?.apiKey))}`);
162
+ }
163
+ else {
164
+ const apiKeyEnvName = Array.isArray(m.apiKeyEnvName) ? m.apiKeyEnvName : [m.apiKeyEnvName];
165
+ const envKeyName = apiKeyEnvName.find((name) => name && process.env[name]);
166
+ if (envKeyName) {
167
+ lines.push(`${chalk_1.default.cyan("API Key")}: ${chalk_1.default.green(maskApiKey(process.env[envKeyName]))}`);
168
+ }
169
+ else {
170
+ lines.push(`${chalk_1.default.cyan("API Key")}: ${chalk_1.default.yellow("Not found")}`);
171
+ }
172
+ }
173
+ console.log("\n");
174
+ console.log((0, boxen_1.default)(lines.join("\n"), {
175
+ padding: 1,
176
+ borderStyle: "classic",
177
+ borderColor: "cyan",
178
+ }));
179
+ console.log("\n");
180
+ }
181
+ async function loadModel(model, modelOptions, options) {
182
+ const params = {
183
+ model: MODEL_NAME ?? model?.name ?? undefined,
184
+ temperature: model?.temperature ?? undefined,
185
+ topP: model?.topP ?? undefined,
186
+ frequencyPenalty: model?.frequencyPenalty ?? undefined,
187
+ presencePenalty: model?.presencePenalty ?? undefined,
188
+ };
189
+ const provider = (MODEL_PROVIDER ?? model?.provider ?? constants_js_1.DEFAULT_MODEL_PROVIDER).replace(/-/g, "");
190
+ const models = availableModels();
191
+ const m = findModel(models, provider);
192
+ if (!m)
193
+ throw new Error(`Unsupported model: ${model?.provider} ${model?.name}`);
194
+ const credential = await (0, credential_js_1.loadCredential)({ ...options, model: `${provider}:${params.model}` });
195
+ printChatModelInfoBox({ provider, model: params.model || "", credential, m });
196
+ return m.create({
197
+ ...(credential || {}),
198
+ model: params.model,
199
+ modelOptions: { ...params, ...modelOptions },
200
+ });
201
+ }