@tacoreai/web-sdk 1.22.1-beta.0 → 1.22.1-beta.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/database/core/apps/AppServerRuntime.js +13 -1
- package/database/core/apps/AppsClient.Data.js +10 -15
- package/database/core/apps/AppsClient.IAM.js +77 -0
- package/database/core/apps/AppsClient.Users.js +30 -0
- package/database/core/apps/AppsClient.js +27 -3
- package/database/core/apps/AppsPublicClient.js +3 -1
- package/database/core/apps/BaseAppsClient.js +31 -20
- package/package.json +1 -1
- package/utils/index.js +2 -5
|
@@ -33,6 +33,8 @@ const getRequestSource = (isPlatformProxyRequest, isSchedulerRequest) => {
|
|
|
33
33
|
const createRequestScopedAppsClient = (env, options = {}) => {
|
|
34
34
|
const {
|
|
35
35
|
accessToken = null,
|
|
36
|
+
appServerApiKey = null,
|
|
37
|
+
clientAppId = env.dataSourceId || env.appId,
|
|
36
38
|
previewAppServerApiKey = null,
|
|
37
39
|
enableAppServerServiceAuth = false,
|
|
38
40
|
} = options;
|
|
@@ -50,11 +52,15 @@ const createRequestScopedAppsClient = (env, options = {}) => {
|
|
|
50
52
|
null;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
if (appServerApiKey) {
|
|
56
|
+
config.appServerApiKey = appServerApiKey;
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
if (previewAppServerApiKey) {
|
|
54
60
|
config.previewAppServerApiKey = previewAppServerApiKey;
|
|
55
61
|
}
|
|
56
62
|
|
|
57
|
-
return new AppsClient(
|
|
63
|
+
return new AppsClient(clientAppId, config);
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
const isPreviewApiKeyShapeValid = (apiKey) => {
|
|
@@ -286,6 +292,7 @@ export const createAppServerRuntime = async (options = {}) => {
|
|
|
286
292
|
process.env.CLOUDFLARE_WORKER_INTEROP_APP_SERVER_TOKEN
|
|
287
293
|
);
|
|
288
294
|
const requestSource = getRequestSource(isPlatformProxyRequest, isSchedulerRequest);
|
|
295
|
+
let appServerApiKey = null;
|
|
289
296
|
let previewAppServerApiKey = null;
|
|
290
297
|
let isExternalApiKeyRequest = false;
|
|
291
298
|
|
|
@@ -313,6 +320,7 @@ export const createAppServerRuntime = async (options = {}) => {
|
|
|
313
320
|
try {
|
|
314
321
|
const authClient = createRequestScopedAppsClient(env, {
|
|
315
322
|
accessToken: requestAccessToken || null,
|
|
323
|
+
clientAppId: env.appId,
|
|
316
324
|
});
|
|
317
325
|
isValidApiKey = await validateExternalApiKey(authClient, env.appId, requestApiKey);
|
|
318
326
|
} catch (error) {
|
|
@@ -333,6 +341,7 @@ export const createAppServerRuntime = async (options = {}) => {
|
|
|
333
341
|
}
|
|
334
342
|
|
|
335
343
|
isExternalApiKeyRequest = true;
|
|
344
|
+
appServerApiKey = requestApiKey;
|
|
336
345
|
|
|
337
346
|
if (isPreviewMode() && !requestAccessToken) {
|
|
338
347
|
previewAppServerApiKey = requestApiKey;
|
|
@@ -347,16 +356,19 @@ export const createAppServerRuntime = async (options = {}) => {
|
|
|
347
356
|
hasPlatformInteropHeader: Boolean(platformInteropHeader),
|
|
348
357
|
hasSchedulerInteropHeader: Boolean(schedulerInteropHeader),
|
|
349
358
|
isExternalApiKeyRequest,
|
|
359
|
+
willForwardAppServerApiKey: Boolean(appServerApiKey && !requestAccessToken),
|
|
350
360
|
willForwardPreviewAppServerApiKey: Boolean(previewAppServerApiKey),
|
|
351
361
|
});
|
|
352
362
|
|
|
353
363
|
const appsClient = createRequestScopedAppsClient(env, {
|
|
354
364
|
accessToken: requestAccessToken || null,
|
|
365
|
+
appServerApiKey: requestAccessToken ? null : appServerApiKey,
|
|
355
366
|
previewAppServerApiKey,
|
|
356
367
|
enableAppServerServiceAuth: Boolean((isSchedulerRequest || isExternalApiKeyRequest) && !requestAccessToken),
|
|
357
368
|
});
|
|
358
369
|
console.log(`[AppServer Debug] scoped AppsClient api="${apiName}"`, {
|
|
359
370
|
hasAccessToken: Boolean(appsClient.getAccessToken()),
|
|
371
|
+
hasAppServerApiKey: Boolean(appsClient.config.appServerApiKey),
|
|
360
372
|
hasPreviewAppServerApiKey: Boolean(appsClient.config.previewAppServerApiKey),
|
|
361
373
|
hasInteropKey: Boolean(appsClient.config.tacoreServerInteropAppServerApiKey),
|
|
362
374
|
serviceAuthEnabled: appsClient.config.enableAppServerServiceAuth === true,
|
|
@@ -80,22 +80,11 @@ export const appsClientDataMethods = {
|
|
|
80
80
|
modelName: modelName,
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
if (typeof query
|
|
84
|
-
|
|
85
|
-
} else if (query && typeof query === "object") {
|
|
86
|
-
const { page = 1, pageSize = 20, fields, filter } = query;
|
|
87
|
-
params.page = Math.max(1, parseInt(page));
|
|
88
|
-
params.pageSize = parseInt(pageSize) || 1000;
|
|
89
|
-
console.log(params);
|
|
90
|
-
if (fields && Array.isArray(fields)) {
|
|
91
|
-
params.fields = fields;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (filter && typeof filter === "object") {
|
|
95
|
-
params.filter = filter;
|
|
96
|
-
}
|
|
83
|
+
if (typeof query !== "string" || !query) {
|
|
84
|
+
throw new Error("readData only supports single-record reads by wyID. Use invoke('data/list', ...) or invoke('data/query', ...) for list/query reads.");
|
|
97
85
|
}
|
|
98
86
|
|
|
87
|
+
params.wyID = query;
|
|
99
88
|
const result = await this._get("/apps/data/read", params);
|
|
100
89
|
|
|
101
90
|
if (result.data === null && params.wyID) {
|
|
@@ -152,7 +141,13 @@ export const appsClientDataMethods = {
|
|
|
152
141
|
async hasData(modelName) {
|
|
153
142
|
try {
|
|
154
143
|
if (!modelName) throw new Error("modelName is required for hasData");
|
|
155
|
-
const result = await this.
|
|
144
|
+
const result = await this.invoke("data/list", {
|
|
145
|
+
modelName,
|
|
146
|
+
query: {
|
|
147
|
+
page: 1,
|
|
148
|
+
pageSize: 1,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
156
151
|
return result && result.data && result.data.length > 0;
|
|
157
152
|
} catch (error) {
|
|
158
153
|
console.error(`检查应用数据失败 (model: ${modelName}):`, error);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const appsClientIamMethods = {
|
|
2
|
+
async getIamContext(params = {}) {
|
|
3
|
+
return this._post("/apps/iam/me", params);
|
|
4
|
+
},
|
|
5
|
+
|
|
6
|
+
async bootstrapIam(params = {}) {
|
|
7
|
+
return this._post("/apps/iam/bootstrap", params);
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
async listIamOrgUnits(params = {}) {
|
|
11
|
+
return this._post("/apps/iam/org-units/list", params);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
async createIamOrgUnit(params = {}) {
|
|
15
|
+
return this._post("/apps/iam/org-units", params);
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
async updateIamOrgUnit(params = {}) {
|
|
19
|
+
return this._post("/apps/iam/org-units/update", params);
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async deleteIamOrgUnit(params = {}) {
|
|
23
|
+
return this._post("/apps/iam/org-units/delete", params);
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
async listIamRoles(params = {}) {
|
|
27
|
+
return this._post("/apps/iam/roles/list", params);
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
async createIamRole(params = {}) {
|
|
31
|
+
return this._post("/apps/iam/roles", params);
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
async updateIamRole(params = {}) {
|
|
35
|
+
return this._post("/apps/iam/roles/update", params);
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async deleteIamRole(params = {}) {
|
|
39
|
+
return this._post("/apps/iam/roles/delete", params);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
async listIamStaff(params = {}) {
|
|
43
|
+
return this._post("/apps/iam/staff/list", params);
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
async createIamStaff(params = {}) {
|
|
47
|
+
return this._post("/apps/iam/staff", params);
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
async updateIamStaff(params = {}) {
|
|
51
|
+
return this._post("/apps/iam/staff/update", params);
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
async deleteIamStaff(params = {}) {
|
|
55
|
+
return this._post("/apps/iam/staff/delete", params);
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
async listModelPolicies(params = {}) {
|
|
59
|
+
return this._post("/apps/data/model-policies/list", params);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
async declareModelPolicy(params = {}) {
|
|
63
|
+
return this._post("/apps/data/model-policies/declare", params);
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
async writeAuditLog(params = {}) {
|
|
67
|
+
return this._post("/apps/audit/write", params);
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
async queryAuditLogs(params = {}) {
|
|
71
|
+
return this._post("/apps/audit/query", params);
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
async authorizeFileDownload(params = {}) {
|
|
75
|
+
return this._post("/apps/files/authorize-download", params);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
@@ -62,4 +62,34 @@ export const appsClientUserMethods = {
|
|
|
62
62
|
password,
|
|
63
63
|
});
|
|
64
64
|
},
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 从当前应用移除用户访问权限,保留 Auth 账号。
|
|
68
|
+
* @param {Object} params { userId: string }
|
|
69
|
+
* @returns {Promise<{success: boolean, data: {userId: string, appId: string}}>}
|
|
70
|
+
*/
|
|
71
|
+
async removeAppUser({ userId }) {
|
|
72
|
+
if (!userId) {
|
|
73
|
+
throw new Error("userId is required.");
|
|
74
|
+
}
|
|
75
|
+
return this._post("/apps/users/remove", {
|
|
76
|
+
appId: this.appId,
|
|
77
|
+
targetUserId: userId,
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 彻底删除当前应用中的用户账号,使该邮箱可重新注册。
|
|
83
|
+
* @param {Object} params { userId: string }
|
|
84
|
+
* @returns {Promise<{success: boolean, data: {userId: string, appId: string, deletionMode: string, authDeleted: boolean}}>}
|
|
85
|
+
*/
|
|
86
|
+
async deleteAppUser({ userId }) {
|
|
87
|
+
if (!userId) {
|
|
88
|
+
throw new Error("userId is required.");
|
|
89
|
+
}
|
|
90
|
+
return this._post("/apps/users/delete", {
|
|
91
|
+
appId: this.appId,
|
|
92
|
+
targetUserId: userId,
|
|
93
|
+
});
|
|
94
|
+
},
|
|
65
95
|
};
|
|
@@ -18,6 +18,7 @@ import { appsClientToolsMethods } from "./AppsClient.Tools.js";
|
|
|
18
18
|
import { appsClientDebugMethods } from "./AppsClient.Debug.js";
|
|
19
19
|
import { appsClientCrawlerMethods } from "./AppsClient.Crawler.js";
|
|
20
20
|
import { appsClientWechatMethods } from "./AppsClient.Wechat.js";
|
|
21
|
+
import { appsClientIamMethods } from "./AppsClient.IAM.js";
|
|
21
22
|
|
|
22
23
|
const instanceMap = new Map();
|
|
23
24
|
/**
|
|
@@ -79,8 +80,7 @@ class AppsClient extends BaseAppsClient {
|
|
|
79
80
|
return this.readData(modelName, rest.wyID);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
return this.readData(modelName, rest);
|
|
83
|
+
throw new Error("readData only supports single-record reads by wyID. Use invoke('data/list', ...) or invoke('data/query', ...) for list/query reads.");
|
|
84
84
|
},
|
|
85
85
|
|
|
86
86
|
"deleteData": ({ modelName, wyID, options }) =>
|
|
@@ -103,8 +103,31 @@ class AppsClient extends BaseAppsClient {
|
|
|
103
103
|
"createRole": params => this.createRole(params),
|
|
104
104
|
"updateUserRole": params => this.updateUserRole(params),
|
|
105
105
|
"users/update-password": params => this.updateUserPassword(params),
|
|
106
|
+
"users/remove": params => this.removeAppUser(params),
|
|
107
|
+
"users/delete": params => this.deleteAppUser(params),
|
|
106
108
|
"listAppUsers": params => this.listAppUsers(params),
|
|
107
109
|
|
|
110
|
+
// === 企业 IAM / 审计 / 文件鉴权 ===
|
|
111
|
+
"iam/me": params => this.getIamContext(params),
|
|
112
|
+
"iam/bootstrap": params => this.bootstrapIam(params),
|
|
113
|
+
"iam/org-units/list": params => this.listIamOrgUnits(params),
|
|
114
|
+
"iam/org-units": params => this.createIamOrgUnit(params),
|
|
115
|
+
"iam/org-units/update": params => this.updateIamOrgUnit(params),
|
|
116
|
+
"iam/org-units/delete": params => this.deleteIamOrgUnit(params),
|
|
117
|
+
"iam/roles/list": params => this.listIamRoles(params),
|
|
118
|
+
"iam/roles": params => this.createIamRole(params),
|
|
119
|
+
"iam/roles/update": params => this.updateIamRole(params),
|
|
120
|
+
"iam/roles/delete": params => this.deleteIamRole(params),
|
|
121
|
+
"iam/staff/list": params => this.listIamStaff(params),
|
|
122
|
+
"iam/staff": params => this.createIamStaff(params),
|
|
123
|
+
"iam/staff/update": params => this.updateIamStaff(params),
|
|
124
|
+
"iam/staff/delete": params => this.deleteIamStaff(params),
|
|
125
|
+
"data/model-policies/list": params => this.listModelPolicies(params),
|
|
126
|
+
"data/model-policies/declare": params => this.declareModelPolicy(params),
|
|
127
|
+
"audit/write": params => this.writeAuditLog(params),
|
|
128
|
+
"audit/query": params => this.queryAuditLogs(params),
|
|
129
|
+
"files/authorize-download": params => this.authorizeFileDownload(params),
|
|
130
|
+
|
|
108
131
|
// === 文件存储 ===
|
|
109
132
|
"uploadFile": ({ file }) => this.uploadFile(file),
|
|
110
133
|
"uploadToR2": ({ file }) => this.uploadToR2(file),
|
|
@@ -213,7 +236,8 @@ Object.assign(
|
|
|
213
236
|
appsClientToolsMethods,
|
|
214
237
|
appsClientDebugMethods,
|
|
215
238
|
appsClientCrawlerMethods,
|
|
216
|
-
appsClientWechatMethods
|
|
239
|
+
appsClientWechatMethods,
|
|
240
|
+
appsClientIamMethods
|
|
217
241
|
);
|
|
218
242
|
|
|
219
243
|
export { AppsClient };
|
|
@@ -4,8 +4,10 @@ import { BaseAppsClient } from "./BaseAppsClient.js";
|
|
|
4
4
|
* AI应用公共数据客户端 - 无需认证
|
|
5
5
|
*
|
|
6
6
|
* 核心理念:
|
|
7
|
-
* -
|
|
7
|
+
* - 通过继承的通用 invoke(path, params) 调用匿名公开接口。
|
|
8
|
+
* - 用于匿名读取模型策略 `publicRead` 明确开放的 CMS 数据。
|
|
8
9
|
* - 用于匿名提交数据到指定的、允许公开写入的模型。
|
|
10
|
+
* - 保留 `readConfiguredPublicData` 兼容旧 publicConfig 公开读。
|
|
9
11
|
* - 此客户端的所有操作都无需用户登录。
|
|
10
12
|
*/
|
|
11
13
|
export class AppsPublicClient extends BaseAppsClient {
|
|
@@ -2,10 +2,11 @@ import { getAppsApiBaseUrl, isBrowser, isBackend, isSSR, getGlobalOptions } from
|
|
|
2
2
|
|
|
3
3
|
const ACCESS_TOKEN_STORAGE_KEY = "tacoreai_apps_access_token";
|
|
4
4
|
const PREVIEW_APPSERVER_API_KEY_HEADER = "x-tacore-preview-app-server-api-key";
|
|
5
|
+
const APP_SERVER_API_KEY_HEADER = "x-tacore-app-server-api-key";
|
|
5
6
|
const APP_SERVER_SERVICE_TOKEN_HEADER = "x-tacore-app-server-service-token";
|
|
6
7
|
const APP_SERVER_OWNER_APP_ID_HEADER = "x-tacore-app-server-owner-app-id";
|
|
7
|
-
const
|
|
8
|
-
"
|
|
8
|
+
const APP_SERVER_SERVICE_CREDENTIAL_REQUIRED_ERROR =
|
|
9
|
+
"AppServer service credential is required for backend service auth. Provide TACORE_SERVER_INTEROP_APP_SERVER_API_KEY + TACORE_APP_SERVER_SERVICE_TOKEN, or forward a validated appServerApiKey.";
|
|
9
10
|
|
|
10
11
|
const normalizeAccessToken = (value) => {
|
|
11
12
|
if (typeof value !== "string") {
|
|
@@ -50,7 +51,17 @@ const writePersistedAccessToken = (token) => {
|
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
const isBackendPreviewMode = () => isBackend && process.env.TACORE_APPSERVER_PREVIEW_MODE === "true";
|
|
53
|
-
const
|
|
54
|
+
const hasAppServerServiceCredential = (config = {}) => {
|
|
55
|
+
if (config.tacoreServerInteropAppServerApiKey && config.tacoreAppServerServiceToken) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (config.appServerApiKey) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return isBackendPreviewMode() && Boolean(config.previewAppServerApiKey);
|
|
62
|
+
};
|
|
63
|
+
const shouldRequireAppServerServiceCredential = (config = {}) =>
|
|
64
|
+
isBackend && !isSSR && config.enableAppServerServiceAuth === true;
|
|
54
65
|
|
|
55
66
|
/**
|
|
56
67
|
* Apps SDK 基类
|
|
@@ -96,8 +107,8 @@ export class BaseAppsClient {
|
|
|
96
107
|
this.config.tacoreAppServerServiceToken = process.env.TACORE_APP_SERVER_SERVICE_TOKEN;
|
|
97
108
|
}
|
|
98
109
|
|
|
99
|
-
if (
|
|
100
|
-
throw new Error(
|
|
110
|
+
if (shouldRequireAppServerServiceCredential(this.config) && !hasAppServerServiceCredential(this.config)) {
|
|
111
|
+
throw new Error(APP_SERVER_SERVICE_CREDENTIAL_REQUIRED_ERROR);
|
|
101
112
|
}
|
|
102
113
|
}
|
|
103
114
|
|
|
@@ -167,10 +178,6 @@ export class BaseAppsClient {
|
|
|
167
178
|
...additionalHeaders,
|
|
168
179
|
};
|
|
169
180
|
|
|
170
|
-
if (this.config.datasource) {
|
|
171
|
-
headers["x-datasource"] = this.config.datasource;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
181
|
if (this.config.supabaseBaseUrl) {
|
|
175
182
|
headers["x-supabase-base-url"] = this.config.supabaseBaseUrl;
|
|
176
183
|
}
|
|
@@ -196,17 +203,20 @@ export class BaseAppsClient {
|
|
|
196
203
|
headers["Authorization"] = `Bearer ${token}`;
|
|
197
204
|
}
|
|
198
205
|
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
this.config.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
if (isBackend && !isSSR && !token && this.config.enableAppServerServiceAuth === true) {
|
|
207
|
+
if (this.config.tacoreServerInteropAppServerApiKey && this.config.tacoreAppServerServiceToken) {
|
|
208
|
+
headers["x-tacore-server-interop-app-server-api-key"] = this.config.tacoreServerInteropAppServerApiKey;
|
|
209
|
+
headers[APP_SERVER_SERVICE_TOKEN_HEADER] = this.config.tacoreAppServerServiceToken;
|
|
210
|
+
headers[APP_SERVER_OWNER_APP_ID_HEADER] = this.config.appServerOwnerAppId || this.config.appId || process.env.APP_ID || this.appId;
|
|
211
|
+
} else if (this.config.appServerApiKey && !headers[APP_SERVER_API_KEY_HEADER]) {
|
|
212
|
+
headers[APP_SERVER_API_KEY_HEADER] = this.config.appServerApiKey;
|
|
213
|
+
} else if (
|
|
214
|
+
isBackendPreviewMode() &&
|
|
215
|
+
this.config.previewAppServerApiKey &&
|
|
216
|
+
!headers[PREVIEW_APPSERVER_API_KEY_HEADER]
|
|
217
|
+
) {
|
|
218
|
+
headers[PREVIEW_APPSERVER_API_KEY_HEADER] = this.config.previewAppServerApiKey;
|
|
219
|
+
}
|
|
210
220
|
} else if (
|
|
211
221
|
isBackendPreviewMode() &&
|
|
212
222
|
!token &&
|
|
@@ -323,6 +333,7 @@ export class BaseAppsClient {
|
|
|
323
333
|
getConfig() {
|
|
324
334
|
const config = { ...this.config };
|
|
325
335
|
delete config.accessToken;
|
|
336
|
+
delete config.appServerApiKey;
|
|
326
337
|
delete config.previewAppServerApiKey;
|
|
327
338
|
return config;
|
|
328
339
|
}
|
package/package.json
CHANGED
package/utils/index.js
CHANGED
|
@@ -54,11 +54,8 @@ export function getAppsApiBaseUrl() {
|
|
|
54
54
|
}
|
|
55
55
|
// 后端环境逻辑
|
|
56
56
|
if (isBackend) {
|
|
57
|
-
// stone 手动:
|
|
58
|
-
const baseUrl = process.env.TACORE_SERVER_INTRANET_BASE_URL;
|
|
59
|
-
if (!baseUrl) {
|
|
60
|
-
throw new Error("TACORE_SERVER_INTRANET_BASE_URL environment variable is not set in the backend environment.");
|
|
61
|
-
}
|
|
57
|
+
// stone 手动:tacore server 地址,优先使用内网地址,兜底走公网(比如平台外本地部署)
|
|
58
|
+
const baseUrl = process.env.TACORE_SERVER_INTRANET_BASE_URL || 'https://api.tacore.chat';
|
|
62
59
|
return baseUrl;
|
|
63
60
|
}
|
|
64
61
|
|