hiwork-core 0.0.24 → 0.0.30
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/cordis.patch.yml +20 -4
- package/lib/ai-router-client.js +142 -1
- package/lib/client.js +1001 -3
- package/lib/index.js +1874 -92
- package/lib/knowledge-config.js +273 -0
- package/lib/pms-client.js +95 -3
- package/lib/types/ai-router-client.d.ts +61 -0
- package/lib/types/client/hero-greeting.d.ts +0 -11
- package/lib/types/client/styles.d.ts +28 -0
- package/lib/types/client/types.d.ts +13 -1
- package/lib/types/client/voice/MicButton.d.ts +24 -0
- package/lib/types/client/voice/VoiceOverlay.d.ts +37 -0
- package/lib/types/client/voice/composer.d.ts +98 -0
- package/lib/types/client/voice/entry.d.ts +72 -0
- package/lib/types/client/voice/recording.d.ts +57 -0
- package/lib/types/client/voice/voice-data.d.ts +101 -0
- package/lib/types/client/voice/voice-styles.d.ts +9 -0
- package/lib/types/index.d.ts +3 -1
- package/lib/types/knowledge-config.d.ts +115 -0
- package/lib/types/pms-client.d.ts +41 -0
- package/lib/types/voice-rpc.d.ts +133 -0
- package/lib/types/web-search.d.ts +123 -0
- package/lib/voice-rpc.js +211 -0
- package/lib/web-search.js +259 -0
- package/package.json +4 -2
- package/lib/types/client/daily-items.d.ts +0 -25
package/lib/index.js
CHANGED
|
@@ -3137,7 +3137,7 @@ function isUnloading(ctx) {
|
|
|
3137
3137
|
}
|
|
3138
3138
|
|
|
3139
3139
|
// src/version.ts
|
|
3140
|
-
var PKG_VERSION = false ? "dev" : "0.0.
|
|
3140
|
+
var PKG_VERSION = false ? "dev" : "0.0.30";
|
|
3141
3141
|
|
|
3142
3142
|
// src/ai-router-client.ts
|
|
3143
3143
|
var AUTH_AUTHORIZE_PATH = "/api/auth/authorize";
|
|
@@ -3157,6 +3157,19 @@ var ME_SKILL_PACKAGES_PATH = "/api/me/skill-packages";
|
|
|
3157
3157
|
var ME_WORKBENCH_APPS_PATH = "/api/me/workbench-apps";
|
|
3158
3158
|
var ME_OFFICE_CONFIG_PATH = "/api/me/office-config";
|
|
3159
3159
|
var ME_OFFICE_RELAY_DOCUMENTS_PATH = "/api/me/office-relay/documents";
|
|
3160
|
+
var ME_VOICE_CONFIG_PATH = "/api/me/voice-config";
|
|
3161
|
+
var ME_VOICE_TRANSCRIBE_PATH = "/api/me/voice-transcribe";
|
|
3162
|
+
var VOICE_TRANSCRIBE_TIMEOUT_MS = 6e4;
|
|
3163
|
+
var VOICE_CONFIG_FALLBACK_MAX_SECONDS = 60;
|
|
3164
|
+
var VOICE_ERROR_FALLBACK_MESSAGE = {
|
|
3165
|
+
VOICE_DISABLED: "\u672C\u90E8\u7F72\u672A\u542F\u7528\u8BED\u97F3\u8BC6\u522B\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458",
|
|
3166
|
+
VOICE_NOT_CONFIGURED: "\u672C\u90E8\u7F72\u5C1A\u672A\u914D\u7F6E\u8BED\u97F3\u8BC6\u522B\u670D\u52A1\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458",
|
|
3167
|
+
VOICE_LIMIT_REACHED: "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",
|
|
3168
|
+
VOICE_AUDIO_TOO_LARGE: "\u5F55\u97F3\u8FC7\u957F\u6216\u6587\u4EF6\u8FC7\u5927\uFF0C\u8BF7\u7F29\u77ED\u540E\u91CD\u8BD5",
|
|
3169
|
+
VOICE_BAD_REQUEST: "\u5F55\u97F3\u6570\u636E\u4E0D\u5408\u6CD5\uFF0C\u8BF7\u91CD\u65B0\u5F55\u5236",
|
|
3170
|
+
VOICE_UPSTREAM: "\u8BED\u97F3\u8BC6\u522B\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"
|
|
3171
|
+
};
|
|
3172
|
+
var VOICE_ERROR_DEFAULT_MESSAGE = "\u8BED\u97F3\u8BC6\u522B\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
3160
3173
|
var DEFAULT_CLIENT_ID = "hiwork-desktop";
|
|
3161
3174
|
var DEFAULT_REDIRECT_URI = "hiwork://auth/callback";
|
|
3162
3175
|
var GatewayError = class extends Error {
|
|
@@ -3548,6 +3561,81 @@ var AiRouterClient = class {
|
|
|
3548
3561
|
if (!res.ok) throw new GatewayError("GATEWAY_UNREACHABLE", `\u7F51\u5173\u8FD4\u56DE\u9519\u8BEF\uFF08HTTP ${res.status}\uFF09`, res.status);
|
|
3549
3562
|
return await parseMeJson(res);
|
|
3550
3563
|
}
|
|
3564
|
+
/**
|
|
3565
|
+
* GET /api/me/voice-config:当前账号的语音识别开关与录音时长上限。
|
|
3566
|
+
*
|
|
3567
|
+
* 与每日一句的 `getMyDailyQuote` 同款,**这两个方法不在 {@link GatewayClient} 接口上**:
|
|
3568
|
+
* 那个接口是编排层的端口,「语音识别」与它无关,加进去只会逼着每处编排层假网关
|
|
3569
|
+
* (tests/orchestration.spec.ts 里一堆)都补两个用不到的桩。频道侧改用结构子集
|
|
3570
|
+
* `VoiceGatewayPort`(见 `src/voice-rpc.ts`),与 usage / daily 三处一致。
|
|
3571
|
+
*
|
|
3572
|
+
* 与 {@link getMyMcpAssignments} 同样的理由**不复用 `getMeJson`**:那条路径把 403 映射成
|
|
3573
|
+
* `NO_KEY_ASSIGNED`(「尚未被分配虚拟 KEY」),而本端点的鉴权只有会话——一个还没被分配
|
|
3574
|
+
* Key 的账号照样应该有语音识别(分能力与分 Key 是两件事)。沿用它的文案会把「没有 Key」
|
|
3575
|
+
* 错报成原因。
|
|
3576
|
+
*
|
|
3577
|
+
* 本端点契约**恒 200**(开关开与关都是 200 + `enabled` 布尔),因此除 401 以外没有任何
|
|
3578
|
+
* 需要单独解释的拒绝语义:403 / 404 / 5xx / 反代错误页一律收敛成 `GATEWAY_UNREACHABLE`。
|
|
3579
|
+
*
|
|
3580
|
+
* 形状收敛(**本层负责**,消费方拿到的永远是一个合法的 {@link GatewayVoiceConfig}):
|
|
3581
|
+
* 网关线上是 snake_case `max_audio_seconds`,这里转 camelCase;字段缺失 / 类型不符
|
|
3582
|
+
* 按「禁用 + 60 秒」处理——配置读不出来时话筒本就该消失,用一个 undefined 让消费方
|
|
3583
|
+
* 去猜是把形状问题推给下游。真正的「读不到就回落」再往上一层(`src/voice-rpc.ts`)。
|
|
3584
|
+
*/
|
|
3585
|
+
async getMyVoiceConfig(sessionCookie) {
|
|
3586
|
+
const res = await this.requestOrUnreachable(ME_VOICE_CONFIG_PATH, { method: "GET", sessionCookie });
|
|
3587
|
+
if (res.status === 401) throw new GatewayError("SESSION_EXPIRED", "\u7F51\u5173\u4F1A\u8BDD\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55", 401);
|
|
3588
|
+
if (!res.ok) throw new GatewayError("GATEWAY_UNREACHABLE", `\u7F51\u5173\u8FD4\u56DE\u9519\u8BEF\uFF08HTTP ${res.status}\uFF09`, res.status);
|
|
3589
|
+
const data = await parseMeJson(res);
|
|
3590
|
+
const seconds = data.max_audio_seconds;
|
|
3591
|
+
return {
|
|
3592
|
+
enabled: data.enabled === true,
|
|
3593
|
+
maxDurationSeconds: typeof seconds === "number" && Number.isFinite(seconds) && seconds > 0 ? seconds : VOICE_CONFIG_FALLBACK_MAX_SECONDS
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
/**
|
|
3597
|
+
* POST /api/me/voice-transcribe:把一段录音(base64)交给网关转发上游做识别。
|
|
3598
|
+
*
|
|
3599
|
+
* 状态码映射与服务端 handler 一一对应,**不许合并**:
|
|
3600
|
+
* - 401 = 会话过期(唯一一条能让人做点什么——重新登录——的拒绝);
|
|
3601
|
+
* - 503 = 网关自己发的「功能不可用」,再按响应体 `code` 细分:
|
|
3602
|
+
* `VOICE_NOT_CONFIGURED`(部署没配上游)/ `VOICE_DISABLED`(管理员把开关关了)。
|
|
3603
|
+
* 两者给的提示不同(该找管理员配服务 vs 该找管理员开开关)。
|
|
3604
|
+
* ⚠️ 响应体没有 `code`(非 JSON / 反代错误页)也归 `VOICE_DISABLED`——这条路由的
|
|
3605
|
+
* 503 语义就是「没开」,而**上游故障走 502**(见下),不会伪装成 503;
|
|
3606
|
+
* - 429 / 413 / 400 = 配额 / 超长 / 请求体不合法,三种不同的事,分开映射(合并后
|
|
3607
|
+
* 客户端只会看到一句「识别失败」,413 的人不知道该录短一点);
|
|
3608
|
+
* - 其余(含 502 = 上游出错)→ `VOICE_UPSTREAM`。
|
|
3609
|
+
*
|
|
3610
|
+
* message 一律取网关响应体里的 `message`(网关侧是冻结的中文文案,会直接展示给用户);
|
|
3611
|
+
* 响应体不是合法 JSON / 缺 message 时退回本地兜底文案。**绝不把上游 / 网关原文回显**:
|
|
3612
|
+
* 读取响应体走 {@link readVoiceError}(解析失败即空对象),与 `parseMeJson` 不回显原文同源。
|
|
3613
|
+
*
|
|
3614
|
+
* 超时**单独放宽到 60s**(见 {@link VOICE_TRANSCRIBE_TIMEOUT_MS}):这条要上传录音 +
|
|
3615
|
+
* 等上游识别,构造时的 10s 默认值在这里是误报源。
|
|
3616
|
+
*/
|
|
3617
|
+
async transcribeVoice(sessionCookie, audioBase64) {
|
|
3618
|
+
const res = await this.requestOrUnreachable(ME_VOICE_TRANSCRIBE_PATH, {
|
|
3619
|
+
method: "POST",
|
|
3620
|
+
sessionCookie,
|
|
3621
|
+
body: { audio_base64: audioBase64 },
|
|
3622
|
+
timeoutMs: VOICE_TRANSCRIBE_TIMEOUT_MS
|
|
3623
|
+
});
|
|
3624
|
+
if (res.status === 401) throw new GatewayError("SESSION_EXPIRED", "\u7F51\u5173\u4F1A\u8BDD\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55", 401);
|
|
3625
|
+
if (!res.ok) {
|
|
3626
|
+
const body = await readVoiceError(res);
|
|
3627
|
+
if (res.status === 503) {
|
|
3628
|
+
const code = body.code === "VOICE_NOT_CONFIGURED" ? "VOICE_NOT_CONFIGURED" : "VOICE_DISABLED";
|
|
3629
|
+
throw new GatewayError(code, voiceMessage(code, body), 503);
|
|
3630
|
+
}
|
|
3631
|
+
if (res.status === 429) throw new GatewayError("VOICE_LIMIT_REACHED", voiceMessage("VOICE_LIMIT_REACHED", body), 429);
|
|
3632
|
+
if (res.status === 413) throw new GatewayError("VOICE_AUDIO_TOO_LARGE", voiceMessage("VOICE_AUDIO_TOO_LARGE", body), 413);
|
|
3633
|
+
if (res.status === 400) throw new GatewayError("VOICE_BAD_REQUEST", voiceMessage("VOICE_BAD_REQUEST", body), 400);
|
|
3634
|
+
throw new GatewayError("VOICE_UPSTREAM", voiceMessage("VOICE_UPSTREAM", body), res.status);
|
|
3635
|
+
}
|
|
3636
|
+
const data = await parseMeJson(res);
|
|
3637
|
+
return { text: typeof data.text === "string" ? data.text : "" };
|
|
3638
|
+
}
|
|
3551
3639
|
/**
|
|
3552
3640
|
* /api/me 自助端点的 GET 公共路径:网络异常 → GATEWAY_UNREACHABLE,
|
|
3553
3641
|
* 401/403/400 映射为稳定 code,响应体非 JSON 时不把原文带进异常。
|
|
@@ -3584,7 +3672,7 @@ var AiRouterClient = class {
|
|
|
3584
3672
|
const init = {
|
|
3585
3673
|
method: opts.method,
|
|
3586
3674
|
headers,
|
|
3587
|
-
signal: AbortSignal.timeout(this.timeoutMs)
|
|
3675
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? this.timeoutMs)
|
|
3588
3676
|
};
|
|
3589
3677
|
if (opts.rawBody !== void 0) {
|
|
3590
3678
|
init.body = opts.rawBody.buffer.slice(
|
|
@@ -3652,6 +3740,18 @@ async function parseMeJson(res) {
|
|
|
3652
3740
|
}
|
|
3653
3741
|
return data;
|
|
3654
3742
|
}
|
|
3743
|
+
async function readVoiceError(res) {
|
|
3744
|
+
const data = await readJson(res);
|
|
3745
|
+
if (typeof data !== "object" || data === null) return {};
|
|
3746
|
+
const record = data;
|
|
3747
|
+
return {
|
|
3748
|
+
...typeof record.code === "string" && record.code !== "" ? { code: record.code } : {},
|
|
3749
|
+
...typeof record.message === "string" && record.message.trim() !== "" ? { message: record.message.trim() } : {}
|
|
3750
|
+
};
|
|
3751
|
+
}
|
|
3752
|
+
function voiceMessage(code, body) {
|
|
3753
|
+
return body.message ?? VOICE_ERROR_FALLBACK_MESSAGE[code] ?? VOICE_ERROR_DEFAULT_MESSAGE;
|
|
3754
|
+
}
|
|
3655
3755
|
function isInvalidGrant(payload) {
|
|
3656
3756
|
return typeof payload === "object" && payload !== null && payload.error === "invalid_grant";
|
|
3657
3757
|
}
|
|
@@ -4218,8 +4318,8 @@ function parseAppVersionPayload(raw) {
|
|
|
4218
4318
|
if (keys.length > 0) throw new AppVersionRequestError("bad-request", `\u684C\u9762\u7AEF\u7248\u672C\u8BF7\u6C42\u5305\u542B\u672A\u77E5\u5B57\u6BB5 '${keys[0]}'\u3002`);
|
|
4219
4319
|
}
|
|
4220
4320
|
function normalizedVersion(raw) {
|
|
4221
|
-
const
|
|
4222
|
-
return
|
|
4321
|
+
const version2 = typeof raw === "string" ? raw.trim() : "";
|
|
4322
|
+
return version2 === "" ? null : version2;
|
|
4223
4323
|
}
|
|
4224
4324
|
async function handleAppVersionEndpoint(endpoint, rawPayload, deps, signal) {
|
|
4225
4325
|
try {
|
|
@@ -4652,6 +4752,123 @@ function registerUsageRpc(ctx, deps) {
|
|
|
4652
4752
|
};
|
|
4653
4753
|
}
|
|
4654
4754
|
|
|
4755
|
+
// src/voice-rpc.ts
|
|
4756
|
+
var VOICE_RPC_CHANNEL = "/hiwork-voice";
|
|
4757
|
+
var VOICE_RPC_ENDPOINTS = ["status", "transcribe"];
|
|
4758
|
+
var VoiceRequestError = class extends Error {
|
|
4759
|
+
constructor(code, message) {
|
|
4760
|
+
super(message);
|
|
4761
|
+
this.code = code;
|
|
4762
|
+
this.name = "VoiceRequestError";
|
|
4763
|
+
}
|
|
4764
|
+
};
|
|
4765
|
+
var VOICE_MESSAGE_FALLBACK = {
|
|
4766
|
+
SESSION_EXPIRED: "\u767B\u5F55\u72B6\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55",
|
|
4767
|
+
GATEWAY_UNREACHABLE: "\u7F51\u5173\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
4768
|
+
VOICE_DISABLED: "\u672C\u90E8\u7F72\u672A\u542F\u7528\u8BED\u97F3\u8BC6\u522B\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458",
|
|
4769
|
+
VOICE_NOT_CONFIGURED: "\u672C\u90E8\u7F72\u5C1A\u672A\u914D\u7F6E\u8BED\u97F3\u8BC6\u522B\u670D\u52A1\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458",
|
|
4770
|
+
VOICE_LIMIT_REACHED: "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",
|
|
4771
|
+
VOICE_AUDIO_TOO_LARGE: "\u5F55\u97F3\u8FC7\u957F\uFF0C\u8BF7\u7F29\u77ED\u540E\u91CD\u8BD5",
|
|
4772
|
+
VOICE_BAD_REQUEST: "\u5F55\u97F3\u6570\u636E\u4E0D\u5408\u6CD5\uFF0C\u8BF7\u91CD\u65B0\u5F55\u5236",
|
|
4773
|
+
VOICE_UPSTREAM: "\u8BED\u97F3\u8BC6\u522B\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
4774
|
+
RATE_LIMITED: "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",
|
|
4775
|
+
AUTH_FAILED: "\u767B\u5F55\u72B6\u6001\u5F02\u5E38\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55"
|
|
4776
|
+
};
|
|
4777
|
+
var VOICE_GENERIC_FAILURE_MESSAGE = "\u8BED\u97F3\u8BC6\u522B\u6682\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
4778
|
+
var VOICE_SESSION_EXPIRED_MESSAGE = "\u767B\u5F55\u72B6\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55";
|
|
4779
|
+
var VOICE_FALLBACK_CONFIG = { enabled: false, maxDurationSeconds: 60 };
|
|
4780
|
+
function displayVoiceGatewayMessage(code, message) {
|
|
4781
|
+
const text = typeof message === "string" ? message.trim() : "";
|
|
4782
|
+
if (text === "") return VOICE_MESSAGE_FALLBACK[code] ?? VOICE_GENERIC_FAILURE_MESSAGE;
|
|
4783
|
+
const leaksImplementationDetail = /https?:\/\//i.test(text) || /\bHTTP\s*\d{3}\b/i.test(text) || /\bbaseURL\b/i.test(text);
|
|
4784
|
+
if (leaksImplementationDetail) return VOICE_MESSAGE_FALLBACK[code] ?? VOICE_GENERIC_FAILURE_MESSAGE;
|
|
4785
|
+
return text;
|
|
4786
|
+
}
|
|
4787
|
+
function parseVoicePayload(endpoint, raw) {
|
|
4788
|
+
if (raw === void 0 || raw === null) {
|
|
4789
|
+
if (endpoint === "transcribe") throw new VoiceRequestError("bad-request", "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u7F3A\u5C11 audioBase64\u3002");
|
|
4790
|
+
return {};
|
|
4791
|
+
}
|
|
4792
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
4793
|
+
throw new VoiceRequestError("bad-request", "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u53C2\u6570\u4E0D\u5408\u6CD5\u3002");
|
|
4794
|
+
}
|
|
4795
|
+
const record = raw;
|
|
4796
|
+
const keys = Object.keys(record);
|
|
4797
|
+
if (endpoint === "status") {
|
|
4798
|
+
if (keys.length > 0) throw new VoiceRequestError("bad-request", `\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u5305\u542B\u672A\u77E5\u5B57\u6BB5 '${keys[0]}'\u3002`);
|
|
4799
|
+
return {};
|
|
4800
|
+
}
|
|
4801
|
+
for (const key of keys) {
|
|
4802
|
+
if (key !== "audioBase64") throw new VoiceRequestError("bad-request", `\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u5305\u542B\u672A\u77E5\u5B57\u6BB5 '${key}'\u3002`);
|
|
4803
|
+
}
|
|
4804
|
+
const rawAudio = record["audioBase64"];
|
|
4805
|
+
if (typeof rawAudio !== "string" || rawAudio.trim() === "") {
|
|
4806
|
+
throw new VoiceRequestError("bad-request", "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u7684 audioBase64 \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u3002");
|
|
4807
|
+
}
|
|
4808
|
+
return { audioBase64: rawAudio };
|
|
4809
|
+
}
|
|
4810
|
+
function isVoiceRpcEndpoint(endpoint) {
|
|
4811
|
+
return VOICE_RPC_ENDPOINTS.includes(endpoint);
|
|
4812
|
+
}
|
|
4813
|
+
function isAborted4(signal) {
|
|
4814
|
+
return signal?.aborted === true;
|
|
4815
|
+
}
|
|
4816
|
+
async function handleVoiceEndpoint(endpoint, rawPayload, deps, signal) {
|
|
4817
|
+
try {
|
|
4818
|
+
if (isAborted4(signal)) return failure4("cancelled", "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
4819
|
+
if (!isVoiceRpcEndpoint(endpoint)) {
|
|
4820
|
+
throw new VoiceRequestError("bad-request", `\u672A\u77E5\u7684\u8BED\u97F3\u8BC6\u522B\u7AEF\u70B9 '${endpoint}'`);
|
|
4821
|
+
}
|
|
4822
|
+
const payload = parseVoicePayload(endpoint, rawPayload);
|
|
4823
|
+
const sessionCookie = await deps.resolveSession();
|
|
4824
|
+
if (sessionCookie === void 0 || sessionCookie === "") {
|
|
4825
|
+
return failure4("SESSION_EXPIRED", VOICE_SESSION_EXPIRED_MESSAGE);
|
|
4826
|
+
}
|
|
4827
|
+
const gateway = deps.gateway();
|
|
4828
|
+
if (gateway === void 0) {
|
|
4829
|
+
return failure4("GATEWAY_UNREACHABLE", "\u7F51\u5173\u5730\u5740\u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u300C\u7F51\u5173\u6A21\u578B\u300D\u91CC\u5B8C\u6210\u767B\u5F55");
|
|
4830
|
+
}
|
|
4831
|
+
if (isAborted4(signal)) return failure4("cancelled", "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
4832
|
+
if (endpoint === "status") return { ok: true, value: await readVoiceConfig(gateway, sessionCookie, deps.log) };
|
|
4833
|
+
return { ok: true, value: await transcribe(gateway, sessionCookie, payload) };
|
|
4834
|
+
} catch (error) {
|
|
4835
|
+
if (error instanceof VoiceRequestError) return failure4(error.code, error.message);
|
|
4836
|
+
if (error instanceof GatewayError) {
|
|
4837
|
+
return failure4(error.code, displayVoiceGatewayMessage(error.code, error.message));
|
|
4838
|
+
}
|
|
4839
|
+
deps.log?.(`hiwork-core: \u8BED\u97F3\u8BC6\u522B RPC '${endpoint}' \u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
4840
|
+
return failure4("internal", VOICE_GENERIC_FAILURE_MESSAGE);
|
|
4841
|
+
}
|
|
4842
|
+
}
|
|
4843
|
+
async function readVoiceConfig(gateway, sessionCookie, log) {
|
|
4844
|
+
try {
|
|
4845
|
+
const config = await gateway.getMyVoiceConfig(sessionCookie);
|
|
4846
|
+
return {
|
|
4847
|
+
enabled: config.enabled === true,
|
|
4848
|
+
maxDurationSeconds: config.maxDurationSeconds > 0 ? config.maxDurationSeconds : VOICE_FALLBACK_CONFIG.maxDurationSeconds
|
|
4849
|
+
};
|
|
4850
|
+
} catch (error) {
|
|
4851
|
+
log?.(`hiwork-core: \u8BED\u97F3\u914D\u7F6E\u8BFB\u53D6\u5931\u8D25\uFF0C\u6309\u7981\u7528\u56DE\u843D\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
4852
|
+
return { ...VOICE_FALLBACK_CONFIG };
|
|
4853
|
+
}
|
|
4854
|
+
}
|
|
4855
|
+
async function transcribe(gateway, sessionCookie, payload) {
|
|
4856
|
+
const audioBase64 = payload.audioBase64;
|
|
4857
|
+
if (audioBase64 === void 0) throw new VoiceRequestError("bad-request", "\u8BED\u97F3\u8BC6\u522B\u8BF7\u6C42\u7F3A\u5C11 audioBase64\u3002");
|
|
4858
|
+
const result = await gateway.transcribeVoice(sessionCookie, audioBase64);
|
|
4859
|
+
return { text: result.text };
|
|
4860
|
+
}
|
|
4861
|
+
function failure4(code, message) {
|
|
4862
|
+
return { ok: false, error: { code, message, details: {} } };
|
|
4863
|
+
}
|
|
4864
|
+
function registerVoiceRpc(ctx, deps) {
|
|
4865
|
+
const handler = (endpoint, payload, signal) => handleVoiceEndpoint(endpoint, payload, deps, signal);
|
|
4866
|
+
const remove = ctx.connection.rpc.handle(VOICE_RPC_CHANNEL, handler, { authority: "loopback" });
|
|
4867
|
+
return async () => {
|
|
4868
|
+
await remove();
|
|
4869
|
+
};
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4655
4872
|
// src/managed-mcp.ts
|
|
4656
4873
|
var MANAGED_MCP_RPC_CHANNEL = "/hiwork-managed-mcp";
|
|
4657
4874
|
var MANAGED_MCP_RPC_ENDPOINTS = ["snapshot", "refresh", "assertion"];
|
|
@@ -4816,12 +5033,12 @@ var ManagedMcpStore = class {
|
|
|
4816
5033
|
}
|
|
4817
5034
|
}
|
|
4818
5035
|
};
|
|
4819
|
-
function
|
|
5036
|
+
function isAborted5(signal) {
|
|
4820
5037
|
return signal?.aborted === true;
|
|
4821
5038
|
}
|
|
4822
5039
|
async function handleManagedMcpEndpoint(endpoint, rawPayload, deps, store, signal) {
|
|
4823
5040
|
try {
|
|
4824
|
-
if (
|
|
5041
|
+
if (isAborted5(signal)) return failure5("cancelled", "MCP \u6E05\u5355\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
4825
5042
|
if (!isManagedMcpRpcEndpoint(endpoint)) {
|
|
4826
5043
|
throw new ManagedMcpRequestError("bad-request", `\u672A\u77E5\u7684 MCP \u6E05\u5355\u7AEF\u70B9 '${endpoint}'`);
|
|
4827
5044
|
}
|
|
@@ -4842,19 +5059,19 @@ async function handleManagedMcpEndpoint(endpoint, rawPayload, deps, store, signa
|
|
|
4842
5059
|
async function handleAssertion(assignmentId, deps, signal) {
|
|
4843
5060
|
const sessionCookie = await deps.resolveSession();
|
|
4844
5061
|
if (sessionCookie === void 0 || sessionCookie === "") {
|
|
4845
|
-
return
|
|
5062
|
+
return failure5("SESSION_EXPIRED", MANAGED_MCP_SESSION_EXPIRED_MESSAGE);
|
|
4846
5063
|
}
|
|
4847
5064
|
const gateway = deps.gateway();
|
|
4848
5065
|
if (gateway === void 0) {
|
|
4849
|
-
return
|
|
5066
|
+
return failure5("GATEWAY_UNREACHABLE", "\u7F51\u5173\u5730\u5740\u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u300C\u7F51\u5173\u6A21\u578B\u300D\u91CC\u5B8C\u6210\u767B\u5F55");
|
|
4850
5067
|
}
|
|
4851
|
-
if (
|
|
5068
|
+
if (isAborted5(signal)) return failure5("cancelled", "MCP \u6E05\u5355\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
4852
5069
|
const ticket = await gateway.issueMyMcpAssertion(sessionCookie, assignmentId);
|
|
4853
5070
|
const assertion = textOrUndefined(ticket?.assertion);
|
|
4854
5071
|
const mintUrl = textOrUndefined(ticket?.mintUrl);
|
|
4855
5072
|
if (assertion === void 0 || mintUrl === void 0) {
|
|
4856
5073
|
deps.log?.("hiwork-core: \u53D6\u65AD\u8A00\u6536\u5230\u65E0\u6548\u54CD\u5E94\uFF08\u7F3A assertion / mintUrl\uFF09");
|
|
4857
|
-
return
|
|
5074
|
+
return failure5("internal", MANAGED_MCP_GENERIC_FAILURE_MESSAGE);
|
|
4858
5075
|
}
|
|
4859
5076
|
return {
|
|
4860
5077
|
ok: true,
|
|
@@ -4867,7 +5084,7 @@ async function handleAssertion(assignmentId, deps, signal) {
|
|
|
4867
5084
|
}
|
|
4868
5085
|
};
|
|
4869
5086
|
}
|
|
4870
|
-
function
|
|
5087
|
+
function failure5(code, message) {
|
|
4871
5088
|
return { ok: false, error: { code, message, details: {} } };
|
|
4872
5089
|
}
|
|
4873
5090
|
function registerManagedMcpRpc(ctx, deps, store) {
|
|
@@ -5098,12 +5315,12 @@ var ManagedSkillsStore = class {
|
|
|
5098
5315
|
}
|
|
5099
5316
|
}
|
|
5100
5317
|
};
|
|
5101
|
-
function
|
|
5318
|
+
function isAborted6(signal) {
|
|
5102
5319
|
return signal?.aborted === true;
|
|
5103
5320
|
}
|
|
5104
5321
|
async function handleManagedSkillsEndpoint(endpoint, rawPayload, deps, store, signal) {
|
|
5105
5322
|
try {
|
|
5106
|
-
if (
|
|
5323
|
+
if (isAborted6(signal)) return failure6("cancelled", "\u6280\u80FD\u6E05\u5355\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
5107
5324
|
if (!isManagedSkillsRpcEndpoint(endpoint)) {
|
|
5108
5325
|
throw new ManagedSkillsRequestError("bad-request", `\u672A\u77E5\u7684\u6280\u80FD\u6E05\u5355\u7AEF\u70B9 '${endpoint}'`);
|
|
5109
5326
|
}
|
|
@@ -5124,24 +5341,24 @@ async function handleManagedSkillsEndpoint(endpoint, rawPayload, deps, store, si
|
|
|
5124
5341
|
async function handlePackage(assignmentId, deps, signal) {
|
|
5125
5342
|
const sessionCookie = await deps.resolveSession();
|
|
5126
5343
|
if (sessionCookie === void 0 || sessionCookie === "") {
|
|
5127
|
-
return
|
|
5344
|
+
return failure6("SESSION_EXPIRED", MANAGED_SKILLS_SESSION_EXPIRED_MESSAGE);
|
|
5128
5345
|
}
|
|
5129
5346
|
const gateway = deps.gateway();
|
|
5130
5347
|
if (gateway === void 0) {
|
|
5131
|
-
return
|
|
5348
|
+
return failure6("GATEWAY_UNREACHABLE", "\u7F51\u5173\u5730\u5740\u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u300C\u7F51\u5173\u6A21\u578B\u300D\u91CC\u5B8C\u6210\u767B\u5F55");
|
|
5132
5349
|
}
|
|
5133
|
-
if (
|
|
5350
|
+
if (isAborted6(signal)) return failure6("cancelled", "\u6280\u80FD\u6E05\u5355\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
5134
5351
|
const pkg = await gateway.getMySkillPackage(sessionCookie, assignmentId);
|
|
5135
5352
|
const bytes = pkg?.bytes;
|
|
5136
5353
|
const skillName = textOrUndefined2(pkg?.skillName);
|
|
5137
5354
|
const contentSha256 = textOrUndefined2(pkg?.contentSha256);
|
|
5138
5355
|
if (!(bytes instanceof Uint8Array) || bytes.byteLength === 0 || skillName === void 0 || contentSha256 === void 0) {
|
|
5139
5356
|
deps.log?.("hiwork-core: \u53D6\u6280\u80FD\u5305\u6536\u5230\u65E0\u6548\u54CD\u5E94\uFF08\u7F3A skillName / contentSha256 \u6216\u7A7A\u5305\u4F53\uFF09");
|
|
5140
|
-
return
|
|
5357
|
+
return failure6("internal", MANAGED_SKILLS_GENERIC_FAILURE_MESSAGE);
|
|
5141
5358
|
}
|
|
5142
5359
|
if (bytes.byteLength > MAX_MANAGED_SKILL_ARCHIVE_BYTES) {
|
|
5143
5360
|
deps.log?.("hiwork-core: \u6280\u80FD\u5305\u8D85\u8FC7\u5927\u5C0F\u4E0A\u9650\uFF0C\u5DF2\u62D2\u7EDD\u642C\u8FD0");
|
|
5144
|
-
return
|
|
5361
|
+
return failure6(MANAGED_SKILLS_PACKAGE_TOO_LARGE_CODE, MANAGED_SKILLS_PACKAGE_TOO_LARGE_MESSAGE);
|
|
5145
5362
|
}
|
|
5146
5363
|
return {
|
|
5147
5364
|
ok: true,
|
|
@@ -5155,7 +5372,7 @@ async function handlePackage(assignmentId, deps, signal) {
|
|
|
5155
5372
|
}
|
|
5156
5373
|
};
|
|
5157
5374
|
}
|
|
5158
|
-
function
|
|
5375
|
+
function failure6(code, message) {
|
|
5159
5376
|
return { ok: false, error: { code, message, details: {} } };
|
|
5160
5377
|
}
|
|
5161
5378
|
function registerManagedSkillsRpc(ctx, deps, store) {
|
|
@@ -5297,7 +5514,7 @@ function failureOf3(error) {
|
|
|
5297
5514
|
function normalizeSession2(sessionCookie) {
|
|
5298
5515
|
return sessionCookie === void 0 || sessionCookie === "" ? void 0 : sessionCookie;
|
|
5299
5516
|
}
|
|
5300
|
-
function
|
|
5517
|
+
function isAborted7(signal) {
|
|
5301
5518
|
return signal?.aborted === true;
|
|
5302
5519
|
}
|
|
5303
5520
|
var WorkbenchStore = class {
|
|
@@ -5422,7 +5639,7 @@ var WorkbenchStore = class {
|
|
|
5422
5639
|
};
|
|
5423
5640
|
async function handleWorkbenchEndpoint(endpoint, rawPayload, deps, store, signal) {
|
|
5424
5641
|
try {
|
|
5425
|
-
if (
|
|
5642
|
+
if (isAborted7(signal)) return failure7("cancelled", "\u5DE5\u4F5C\u53F0\u6E05\u5355\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
5426
5643
|
if (!isWorkbenchRpcEndpoint(endpoint)) {
|
|
5427
5644
|
throw new WorkbenchRequestError("bad-request", `\u672A\u77E5\u7684\u5DE5\u4F5C\u53F0\u6E05\u5355\u7AEF\u70B9 '${endpoint}'`);
|
|
5428
5645
|
}
|
|
@@ -5435,7 +5652,7 @@ async function handleWorkbenchEndpoint(endpoint, rawPayload, deps, store, signal
|
|
|
5435
5652
|
return { ok: false, error: failureOf3(error) };
|
|
5436
5653
|
}
|
|
5437
5654
|
}
|
|
5438
|
-
function
|
|
5655
|
+
function failure7(code, message) {
|
|
5439
5656
|
return { ok: false, error: { code, message, details: {} } };
|
|
5440
5657
|
}
|
|
5441
5658
|
function registerWorkbenchRpc(ctx, deps, store) {
|
|
@@ -5695,6 +5912,10 @@ var PmsClient = class {
|
|
|
5695
5912
|
* 必须与其余调用逐字相同**(spec §7:统一 10s、令牌只在有身份时发),所以两条路共用这一处,
|
|
5696
5913
|
* 而不是各抄一份、将来各自漂移。
|
|
5697
5914
|
*
|
|
5915
|
+
* **重定向自己跟**(`redirect: 'manual'` + {@link redirectTargetOf}):`fetch` 的默认 `follow` 会把
|
|
5916
|
+
* 重定向后的请求按 fetch 语义**把 POST 改成 GET**,于是请求落在一个只认 POST 的映射上、拿到一个
|
|
5917
|
+
* 「200 + 业务错误信封」,看上去像上游坏了。判据与修法见 {@link PMS_MAX_REDIRECTS}。
|
|
5918
|
+
*
|
|
5698
5919
|
* @param url - 相对路径(拼 {@link PmsClient.baseURL})或**绝对 URL**(原样使用)。
|
|
5699
5920
|
* @param opts - 方法 / 可选 JSON 体 / 可选 Bearer 令牌。
|
|
5700
5921
|
* @returns 原始 `Response`:状态码由调用方判定,本方法不把任何状态码当成错误。
|
|
@@ -5710,10 +5931,19 @@ var PmsClient = class {
|
|
|
5710
5931
|
const init = {
|
|
5711
5932
|
method: opts.method,
|
|
5712
5933
|
headers,
|
|
5713
|
-
|
|
5934
|
+
// 手动跟随:默认的 `follow` 会把重定向后的 POST 降级成 GET(见本方法的抬头)。
|
|
5935
|
+
redirect: "manual"
|
|
5714
5936
|
};
|
|
5715
5937
|
if (opts.body !== void 0) init.body = JSON.stringify(opts.body);
|
|
5716
|
-
|
|
5938
|
+
const deadline = Date.now() + this.timeoutMs;
|
|
5939
|
+
let target = isAbsoluteUrl(url) ? url : `${this.baseURL}${url}`;
|
|
5940
|
+
let response = await fetchWithinDeadline(target, init, deadline);
|
|
5941
|
+
for (let hop = 0; ; hop += 1) {
|
|
5942
|
+
const next = redirectTargetOf(target, response, hop);
|
|
5943
|
+
if (next === void 0) return response;
|
|
5944
|
+
target = next;
|
|
5945
|
+
response = await fetchWithinDeadline(target, init, deadline);
|
|
5946
|
+
}
|
|
5717
5947
|
} catch {
|
|
5718
5948
|
throw new PmsError("UPSTREAM_UNAVAILABLE", PMS_GENERIC_FAILURE_MESSAGE);
|
|
5719
5949
|
}
|
|
@@ -5767,6 +5997,30 @@ function isRecord3(value) {
|
|
|
5767
5997
|
function isAbsoluteUrl(url) {
|
|
5768
5998
|
return /^https?:\/\//i.test(url);
|
|
5769
5999
|
}
|
|
6000
|
+
var PMS_MAX_REDIRECTS = 2;
|
|
6001
|
+
var METHOD_PRESERVING_REDIRECTS = /* @__PURE__ */ new Set([301, 302, 307, 308]);
|
|
6002
|
+
function redirectTargetOf(current, response, hop) {
|
|
6003
|
+
if (!METHOD_PRESERVING_REDIRECTS.has(response.status)) return void 0;
|
|
6004
|
+
if (hop >= PMS_MAX_REDIRECTS) return void 0;
|
|
6005
|
+
const location = response.headers.get("location");
|
|
6006
|
+
if (location === null || location.trim() === "") return void 0;
|
|
6007
|
+
let from2;
|
|
6008
|
+
let next;
|
|
6009
|
+
try {
|
|
6010
|
+
from2 = new URL(current);
|
|
6011
|
+
next = new URL(location.trim(), current);
|
|
6012
|
+
} catch {
|
|
6013
|
+
return void 0;
|
|
6014
|
+
}
|
|
6015
|
+
if (next.protocol !== "https:" && next.protocol !== from2.protocol) return void 0;
|
|
6016
|
+
if (next.hostname !== from2.hostname) return void 0;
|
|
6017
|
+
return next.toString();
|
|
6018
|
+
}
|
|
6019
|
+
async function fetchWithinDeadline(target, init, deadline) {
|
|
6020
|
+
const remaining = deadline - Date.now();
|
|
6021
|
+
if (remaining <= 0) throw new Error("pms request deadline exceeded");
|
|
6022
|
+
return await fetch(target, { ...init, signal: AbortSignal.timeout(remaining) });
|
|
6023
|
+
}
|
|
5770
6024
|
function expiresAtOr(value, fallbackMs) {
|
|
5771
6025
|
if (typeof value === "string" && value !== "" && Number.isFinite(Date.parse(value))) return value;
|
|
5772
6026
|
return new Date(fallbackMs).toISOString();
|
|
@@ -6297,7 +6551,7 @@ var PmsTodoStore = class {
|
|
|
6297
6551
|
};
|
|
6298
6552
|
async function handlePmsTodoEndpoint(endpoint, rawPayload, deps, store, signal) {
|
|
6299
6553
|
try {
|
|
6300
|
-
if (signal?.aborted === true) return
|
|
6554
|
+
if (signal?.aborted === true) return failure8("BAD_REQUEST", PMS_TODO_CANCELLED_MESSAGE);
|
|
6301
6555
|
if (!isPmsTodoRpcEndpoint(endpoint)) {
|
|
6302
6556
|
throw new PmsTodoRequestError(`\u672A\u77E5\u7684 PMS \u5F85\u529E\u7AEF\u70B9 '${endpoint}'`);
|
|
6303
6557
|
}
|
|
@@ -6321,7 +6575,7 @@ async function handlePmsTodoEndpoint(endpoint, rawPayload, deps, store, signal)
|
|
|
6321
6575
|
return { ok: false, error: pmsTodoErrorOf(error) };
|
|
6322
6576
|
}
|
|
6323
6577
|
}
|
|
6324
|
-
function
|
|
6578
|
+
function failure8(code, message) {
|
|
6325
6579
|
return { ok: false, error: { code, message, details: {} } };
|
|
6326
6580
|
}
|
|
6327
6581
|
function registerPmsTodoRpc(ctx, deps, store) {
|
|
@@ -6352,7 +6606,7 @@ function isRecord4(value) {
|
|
|
6352
6606
|
function textOrUndefined4(value) {
|
|
6353
6607
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
6354
6608
|
}
|
|
6355
|
-
function
|
|
6609
|
+
function isAborted8(signal) {
|
|
6356
6610
|
return signal?.aborted === true;
|
|
6357
6611
|
}
|
|
6358
6612
|
function parsePluginUpdatesPayload(endpoint, raw) {
|
|
@@ -6395,7 +6649,7 @@ function toSnapshot(raw) {
|
|
|
6395
6649
|
}
|
|
6396
6650
|
async function handlePluginUpdatesEndpoint(endpoint, rawPayload, deps, signal) {
|
|
6397
6651
|
try {
|
|
6398
|
-
if (
|
|
6652
|
+
if (isAborted8(signal)) return failure9("cancelled", "\u63D2\u4EF6\u66F4\u65B0\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002");
|
|
6399
6653
|
if (!isPluginUpdatesRpcEndpoint(endpoint)) {
|
|
6400
6654
|
throw new PluginUpdatesRequestError("bad-request", `\u672A\u77E5\u7684\u63D2\u4EF6\u66F4\u65B0\u7AEF\u70B9 '${endpoint}'`);
|
|
6401
6655
|
}
|
|
@@ -6411,12 +6665,12 @@ async function handlePluginUpdatesEndpoint(endpoint, rawPayload, deps, signal) {
|
|
|
6411
6665
|
await plugins.applyNow();
|
|
6412
6666
|
return { ok: true, value: { requested: true } };
|
|
6413
6667
|
} catch (error) {
|
|
6414
|
-
if (error instanceof PluginUpdatesRequestError) return
|
|
6668
|
+
if (error instanceof PluginUpdatesRequestError) return failure9(error.code, error.message);
|
|
6415
6669
|
deps.log?.(`hiwork-core: \u63D2\u4EF6\u66F4\u65B0 RPC '${endpoint}' \u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
6416
|
-
return
|
|
6670
|
+
return failure9("internal", PLUGIN_UPDATES_GENERIC_FAILURE_MESSAGE);
|
|
6417
6671
|
}
|
|
6418
6672
|
}
|
|
6419
|
-
function
|
|
6673
|
+
function failure9(code, message) {
|
|
6420
6674
|
return { ok: false, error: { code, message, details: {} } };
|
|
6421
6675
|
}
|
|
6422
6676
|
function registerPluginUpdatesRpc(ctx, deps) {
|
|
@@ -6487,16 +6741,15 @@ function provideIdentity(ctx, deps) {
|
|
|
6487
6741
|
};
|
|
6488
6742
|
}
|
|
6489
6743
|
|
|
6490
|
-
// src/
|
|
6491
|
-
var
|
|
6492
|
-
var
|
|
6493
|
-
var
|
|
6494
|
-
var
|
|
6495
|
-
var MESSAGE_NOT_CONFIGURED = "\u7BA1\u7406\u5458\u8FD8\u6CA1\u5F00\u542F\
|
|
6744
|
+
// src/knowledge-config.ts
|
|
6745
|
+
var HIWORK_KNOWLEDGE_SERVICE = "hiworkKnowledge";
|
|
6746
|
+
var ME_KNOWLEDGE_CONFIG_PATH = "/api/me/knowledge-config";
|
|
6747
|
+
var KNOWLEDGE_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
6748
|
+
var KNOWLEDGE_CONFIG_TIMEOUT_MS = 1e4;
|
|
6749
|
+
var MESSAGE_NOT_CONFIGURED = "\u7BA1\u7406\u5458\u8FD8\u6CA1\u5F00\u542F\u77E5\u8BC6\u5E93\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5F00\u901A";
|
|
6496
6750
|
var MESSAGE_UNAUTHENTICATED = "\u767B\u5F55\u72B6\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55";
|
|
6497
|
-
var MESSAGE_UNREACHABLE = "\
|
|
6498
|
-
var
|
|
6499
|
-
var MESSAGE_GENERIC = "\u8BB0\u5FC6\u914D\u7F6E\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
6751
|
+
var MESSAGE_UNREACHABLE = "\u77E5\u8BC6\u5E93\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
6752
|
+
var MESSAGE_GENERIC = "\u77E5\u8BC6\u5E93\u914D\u7F6E\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
6500
6753
|
function messageFor(reason) {
|
|
6501
6754
|
switch (reason) {
|
|
6502
6755
|
case "not-configured":
|
|
@@ -6509,7 +6762,7 @@ function messageFor(reason) {
|
|
|
6509
6762
|
return MESSAGE_GENERIC;
|
|
6510
6763
|
}
|
|
6511
6764
|
}
|
|
6512
|
-
function
|
|
6765
|
+
function failure10(reason, message) {
|
|
6513
6766
|
return { ok: false, reason, message: message ?? messageFor(reason) };
|
|
6514
6767
|
}
|
|
6515
6768
|
function textOrUndefined6(value) {
|
|
@@ -6517,19 +6770,172 @@ function textOrUndefined6(value) {
|
|
|
6517
6770
|
const text = value.trim();
|
|
6518
6771
|
return text === "" ? void 0 : text;
|
|
6519
6772
|
}
|
|
6773
|
+
function projectKnowledgeConfig(body) {
|
|
6774
|
+
const baseUrl = textOrUndefined6(body["base_url"] ?? body["baseUrl"]);
|
|
6775
|
+
const apiKey = textOrUndefined6(body["api_key"] ?? body["apiKey"]);
|
|
6776
|
+
if (baseUrl === void 0 || apiKey === void 0) return void 0;
|
|
6777
|
+
return {
|
|
6778
|
+
ok: true,
|
|
6779
|
+
baseUrl,
|
|
6780
|
+
apiKey,
|
|
6781
|
+
agentId: textOrUndefined6(body["agent_id"] ?? body["agentId"]) ?? "",
|
|
6782
|
+
chatModelId: textOrUndefined6(body["chat_model_id"] ?? body["chatModelId"]) ?? "",
|
|
6783
|
+
tenantId: textOrUndefined6(body["tenant_id"] ?? body["tenantId"]) ?? ""
|
|
6784
|
+
};
|
|
6785
|
+
}
|
|
6786
|
+
function errorName2(error) {
|
|
6787
|
+
return error instanceof Error ? error.name : typeof error;
|
|
6788
|
+
}
|
|
6789
|
+
function reasonOfErrorCode(error) {
|
|
6790
|
+
const code = error?.code;
|
|
6791
|
+
if (typeof code !== "string") return void 0;
|
|
6792
|
+
switch (code) {
|
|
6793
|
+
case "SESSION_EXPIRED":
|
|
6794
|
+
return "unauthenticated";
|
|
6795
|
+
case "KNOWLEDGE_NOT_CONFIGURED":
|
|
6796
|
+
return "not-configured";
|
|
6797
|
+
case "KNOWLEDGE_UNREACHABLE":
|
|
6798
|
+
case "GATEWAY_UNREACHABLE":
|
|
6799
|
+
return "unreachable";
|
|
6800
|
+
default:
|
|
6801
|
+
return void 0;
|
|
6802
|
+
}
|
|
6803
|
+
}
|
|
6804
|
+
function reasonOfStatus(status) {
|
|
6805
|
+
if (status === 401) return "unauthenticated";
|
|
6806
|
+
if (status === 503) return "not-configured";
|
|
6807
|
+
if (status === 504) return "unreachable";
|
|
6808
|
+
return "error";
|
|
6809
|
+
}
|
|
6810
|
+
var KnowledgeConfigProvider = class {
|
|
6811
|
+
constructor(deps) {
|
|
6812
|
+
this.deps = deps;
|
|
6813
|
+
}
|
|
6814
|
+
cached;
|
|
6815
|
+
async config(opts) {
|
|
6816
|
+
const force = opts?.force === true;
|
|
6817
|
+
let sessionCookie;
|
|
6818
|
+
try {
|
|
6819
|
+
sessionCookie = await this.deps.resolveSession();
|
|
6820
|
+
} catch (error) {
|
|
6821
|
+
this.deps.log?.(`hiwork-core: \u77E5\u8BC6\u5E93\u914D\u7F6E\u83B7\u53D6\u5931\u8D25\uFF08${errorName2(error)}\uFF09`);
|
|
6822
|
+
return failure10("error");
|
|
6823
|
+
}
|
|
6824
|
+
if (sessionCookie === void 0 || sessionCookie === "") return failure10("unauthenticated");
|
|
6825
|
+
if (!force) {
|
|
6826
|
+
const hit = this.cached;
|
|
6827
|
+
if (hit !== void 0 && hit.sessionCookie === sessionCookie && this.now() - hit.at < KNOWLEDGE_CONFIG_TTL_MS) {
|
|
6828
|
+
return hit.view;
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6831
|
+
const gateway = this.deps.gateway();
|
|
6832
|
+
if (gateway === void 0) return failure10("unreachable");
|
|
6833
|
+
let outcome;
|
|
6834
|
+
try {
|
|
6835
|
+
outcome = await gateway.getMyKnowledgeConfig(sessionCookie);
|
|
6836
|
+
} catch (error) {
|
|
6837
|
+
const mapped = reasonOfErrorCode(error);
|
|
6838
|
+
if (mapped !== void 0) return failure10(mapped);
|
|
6839
|
+
this.deps.log?.(`hiwork-core: \u77E5\u8BC6\u5E93\u914D\u7F6E\u83B7\u53D6\u5931\u8D25\uFF08${errorName2(error)}\uFF09`);
|
|
6840
|
+
return failure10("error");
|
|
6841
|
+
}
|
|
6842
|
+
if (!outcome.ok) {
|
|
6843
|
+
if (outcome.kind === "network") return failure10("unreachable");
|
|
6844
|
+
if (outcome.kind === "http") return failure10(reasonOfStatus(outcome.status));
|
|
6845
|
+
return failure10("error");
|
|
6846
|
+
}
|
|
6847
|
+
const view = projectKnowledgeConfig(outcome.body);
|
|
6848
|
+
if (view === void 0) {
|
|
6849
|
+
this.deps.log?.("hiwork-core: \u7F51\u5173\u8FD4\u56DE\u7684 knowledge-config \u4E0D\u5B8C\u6574\uFF08\u7F3A base_url / api_key \u4E4B\u4E00\uFF09");
|
|
6850
|
+
return failure10("error");
|
|
6851
|
+
}
|
|
6852
|
+
this.cached = { sessionCookie, view, at: this.now() };
|
|
6853
|
+
return view;
|
|
6854
|
+
}
|
|
6855
|
+
now() {
|
|
6856
|
+
return (this.deps.now ?? Date.now)();
|
|
6857
|
+
}
|
|
6858
|
+
};
|
|
6859
|
+
function provideKnowledgeConfig(ctx, deps) {
|
|
6860
|
+
const service = new KnowledgeConfigProvider(deps);
|
|
6861
|
+
const dispose = ctx.provide(HIWORK_KNOWLEDGE_SERVICE, service);
|
|
6862
|
+
return typeof dispose === "function" ? dispose : () => {
|
|
6863
|
+
};
|
|
6864
|
+
}
|
|
6865
|
+
function createKnowledgeConfigGateway(baseURL, opts = {}) {
|
|
6866
|
+
const root = baseURL.replace(/\/+$/, "");
|
|
6867
|
+
const timeoutMs = opts.timeoutMs ?? KNOWLEDGE_CONFIG_TIMEOUT_MS;
|
|
6868
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
6869
|
+
return {
|
|
6870
|
+
async getMyKnowledgeConfig(sessionCookie) {
|
|
6871
|
+
try {
|
|
6872
|
+
const res = await doFetch(`${root}${ME_KNOWLEDGE_CONFIG_PATH}`, {
|
|
6873
|
+
method: "GET",
|
|
6874
|
+
headers: {
|
|
6875
|
+
"user-agent": `hiwork-core/${PKG_VERSION}`,
|
|
6876
|
+
cookie: sessionCookie
|
|
6877
|
+
},
|
|
6878
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
6879
|
+
});
|
|
6880
|
+
if (!res.ok) return { ok: false, kind: "http", status: res.status };
|
|
6881
|
+
let body;
|
|
6882
|
+
try {
|
|
6883
|
+
body = await res.json();
|
|
6884
|
+
} catch {
|
|
6885
|
+
return { ok: false, kind: "invalid" };
|
|
6886
|
+
}
|
|
6887
|
+
if (body === null || typeof body !== "object") return { ok: false, kind: "invalid" };
|
|
6888
|
+
return { ok: true, body };
|
|
6889
|
+
} catch {
|
|
6890
|
+
return { ok: false, kind: "network" };
|
|
6891
|
+
}
|
|
6892
|
+
}
|
|
6893
|
+
};
|
|
6894
|
+
}
|
|
6895
|
+
|
|
6896
|
+
// src/memory-config.ts
|
|
6897
|
+
var HIWORK_MEMORY_SERVICE = "hiworkMemory";
|
|
6898
|
+
var ME_MEMORY_CONFIG_PATH = "/api/me/memory-config";
|
|
6899
|
+
var MEMORY_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
6900
|
+
var MEMORY_CONFIG_TIMEOUT_MS = 1e4;
|
|
6901
|
+
var MESSAGE_NOT_CONFIGURED2 = "\u7BA1\u7406\u5458\u8FD8\u6CA1\u5F00\u542F\u56E2\u961F\u8BB0\u5FC6\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5F00\u901A";
|
|
6902
|
+
var MESSAGE_UNAUTHENTICATED2 = "\u767B\u5F55\u72B6\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55";
|
|
6903
|
+
var MESSAGE_UNREACHABLE2 = "\u8BB0\u5FC6\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
6904
|
+
var MESSAGE_NO_GATEWAY = "\u8FD8\u6CA1\u8FDE\u4E0A\u4F01\u4E1A\u7F51\u5173\uFF0C\u8BF7\u5148\u767B\u5F55\u540E\u518D\u8BD5";
|
|
6905
|
+
var MESSAGE_GENERIC2 = "\u8BB0\u5FC6\u914D\u7F6E\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
6906
|
+
function messageFor2(reason) {
|
|
6907
|
+
switch (reason) {
|
|
6908
|
+
case "not-configured":
|
|
6909
|
+
return MESSAGE_NOT_CONFIGURED2;
|
|
6910
|
+
case "unauthenticated":
|
|
6911
|
+
return MESSAGE_UNAUTHENTICATED2;
|
|
6912
|
+
case "unreachable":
|
|
6913
|
+
return MESSAGE_UNREACHABLE2;
|
|
6914
|
+
case "error":
|
|
6915
|
+
return MESSAGE_GENERIC2;
|
|
6916
|
+
}
|
|
6917
|
+
}
|
|
6918
|
+
function failure11(reason, message) {
|
|
6919
|
+
return { ok: false, reason, message: message ?? messageFor2(reason) };
|
|
6920
|
+
}
|
|
6921
|
+
function textOrUndefined7(value) {
|
|
6922
|
+
if (typeof value !== "string") return void 0;
|
|
6923
|
+
const text = value.trim();
|
|
6924
|
+
return text === "" ? void 0 : text;
|
|
6925
|
+
}
|
|
6520
6926
|
function teamIdsOf(value) {
|
|
6521
6927
|
if (!Array.isArray(value)) return [];
|
|
6522
6928
|
const ids = [];
|
|
6523
6929
|
for (const item of value) {
|
|
6524
|
-
const text =
|
|
6930
|
+
const text = textOrUndefined7(item);
|
|
6525
6931
|
if (text !== void 0) ids.push(text);
|
|
6526
6932
|
}
|
|
6527
6933
|
return ids;
|
|
6528
6934
|
}
|
|
6529
6935
|
function projectMemoryConfig(body) {
|
|
6530
|
-
const panelUrl =
|
|
6531
|
-
const serviceId =
|
|
6532
|
-
const apiKey =
|
|
6936
|
+
const panelUrl = textOrUndefined7(body["panel_url"] ?? body["panelUrl"]);
|
|
6937
|
+
const serviceId = textOrUndefined7(body["service_id"] ?? body["serviceId"]);
|
|
6938
|
+
const apiKey = textOrUndefined7(body["api_key"] ?? body["apiKey"] ?? body["userKey"]);
|
|
6533
6939
|
if (panelUrl === void 0 || serviceId === void 0 || apiKey === void 0) return void 0;
|
|
6534
6940
|
return {
|
|
6535
6941
|
ok: true,
|
|
@@ -6539,10 +6945,10 @@ function projectMemoryConfig(body) {
|
|
|
6539
6945
|
apiKey
|
|
6540
6946
|
};
|
|
6541
6947
|
}
|
|
6542
|
-
function
|
|
6948
|
+
function errorName3(error) {
|
|
6543
6949
|
return error instanceof Error ? error.name : typeof error;
|
|
6544
6950
|
}
|
|
6545
|
-
function
|
|
6951
|
+
function reasonOfErrorCode2(error) {
|
|
6546
6952
|
const code = error?.code;
|
|
6547
6953
|
if (typeof code !== "string") return void 0;
|
|
6548
6954
|
switch (code) {
|
|
@@ -6557,7 +6963,7 @@ function reasonOfErrorCode(error) {
|
|
|
6557
6963
|
return void 0;
|
|
6558
6964
|
}
|
|
6559
6965
|
}
|
|
6560
|
-
function
|
|
6966
|
+
function reasonOfStatus2(status) {
|
|
6561
6967
|
if (status === 401) return "unauthenticated";
|
|
6562
6968
|
if (status === 503) return "not-configured";
|
|
6563
6969
|
if (status === 504) return "unreachable";
|
|
@@ -6574,10 +6980,10 @@ var MemoryConfigProvider = class {
|
|
|
6574
6980
|
try {
|
|
6575
6981
|
sessionCookie = await this.deps.resolveSession();
|
|
6576
6982
|
} catch (error) {
|
|
6577
|
-
this.deps.log?.(`hiwork-core: \u8BB0\u5FC6\u914D\u7F6E\u83B7\u53D6\u5931\u8D25\uFF08${
|
|
6578
|
-
return
|
|
6983
|
+
this.deps.log?.(`hiwork-core: \u8BB0\u5FC6\u914D\u7F6E\u83B7\u53D6\u5931\u8D25\uFF08${errorName3(error)}\uFF09`);
|
|
6984
|
+
return failure11("error");
|
|
6579
6985
|
}
|
|
6580
|
-
if (sessionCookie === void 0 || sessionCookie === "") return
|
|
6986
|
+
if (sessionCookie === void 0 || sessionCookie === "") return failure11("unauthenticated");
|
|
6581
6987
|
if (!force) {
|
|
6582
6988
|
const hit = this.cached;
|
|
6583
6989
|
if (hit !== void 0 && hit.sessionCookie === sessionCookie && this.now() - hit.at < MEMORY_CONFIG_TTL_MS) {
|
|
@@ -6585,25 +6991,25 @@ var MemoryConfigProvider = class {
|
|
|
6585
6991
|
}
|
|
6586
6992
|
}
|
|
6587
6993
|
const gateway = this.deps.gateway();
|
|
6588
|
-
if (gateway === void 0) return
|
|
6994
|
+
if (gateway === void 0) return failure11("unreachable", MESSAGE_NO_GATEWAY);
|
|
6589
6995
|
let outcome;
|
|
6590
6996
|
try {
|
|
6591
6997
|
outcome = await gateway.getMyMemoryConfig(sessionCookie);
|
|
6592
6998
|
} catch (error) {
|
|
6593
|
-
const mapped =
|
|
6594
|
-
if (mapped !== void 0) return
|
|
6595
|
-
this.deps.log?.(`hiwork-core: \u8BB0\u5FC6\u914D\u7F6E\u83B7\u53D6\u5931\u8D25\uFF08${
|
|
6596
|
-
return
|
|
6999
|
+
const mapped = reasonOfErrorCode2(error);
|
|
7000
|
+
if (mapped !== void 0) return failure11(mapped);
|
|
7001
|
+
this.deps.log?.(`hiwork-core: \u8BB0\u5FC6\u914D\u7F6E\u83B7\u53D6\u5931\u8D25\uFF08${errorName3(error)}\uFF09`);
|
|
7002
|
+
return failure11("error");
|
|
6597
7003
|
}
|
|
6598
7004
|
if (!outcome.ok) {
|
|
6599
|
-
if (outcome.kind === "network") return
|
|
6600
|
-
if (outcome.kind === "http") return
|
|
6601
|
-
return
|
|
7005
|
+
if (outcome.kind === "network") return failure11("unreachable");
|
|
7006
|
+
if (outcome.kind === "http") return failure11(reasonOfStatus2(outcome.status));
|
|
7007
|
+
return failure11("error");
|
|
6602
7008
|
}
|
|
6603
7009
|
const view = projectMemoryConfig(outcome.body);
|
|
6604
7010
|
if (view === void 0) {
|
|
6605
7011
|
this.deps.log?.("hiwork-core: \u7F51\u5173\u8FD4\u56DE\u7684 memory-config \u4E0D\u5B8C\u6574\uFF08\u7F3A panel_url / service_id / api_key \u4E4B\u4E00\uFF09");
|
|
6606
|
-
return
|
|
7012
|
+
return failure11("error");
|
|
6607
7013
|
}
|
|
6608
7014
|
this.cached = { sessionCookie, view, at: this.now() };
|
|
6609
7015
|
return view;
|
|
@@ -6796,31 +7202,1374 @@ function provideOfficeRelay(ctx, deps) {
|
|
|
6796
7202
|
};
|
|
6797
7203
|
}
|
|
6798
7204
|
|
|
6799
|
-
//
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
var
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
7205
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-llm@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-llm/lib/index.js
|
|
7206
|
+
import { createRequire } from "node:module";
|
|
7207
|
+
|
|
7208
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-typert-protocol/lib/index.js
|
|
7209
|
+
var RemoteError = class extends Error {
|
|
7210
|
+
code;
|
|
7211
|
+
details;
|
|
7212
|
+
/** Structural marker: cross-realm/bundle identification never uses instanceof. */
|
|
7213
|
+
isDSHRemoteError = true;
|
|
7214
|
+
/**
|
|
7215
|
+
* @param code - stable failure code declared in {@link RemoteErrorDetailsMap}.
|
|
7216
|
+
* @param message - human diagnostic carried across the wire.
|
|
7217
|
+
* @param details - structured payload typed by the code.
|
|
7218
|
+
* @param options - standard Error options (`cause` survives in-process only).
|
|
7219
|
+
*/
|
|
7220
|
+
constructor(code, message, details, options) {
|
|
7221
|
+
super(message, options);
|
|
7222
|
+
this.code = code;
|
|
7223
|
+
this.details = details;
|
|
7224
|
+
this.name = "RemoteError";
|
|
7225
|
+
}
|
|
7226
|
+
};
|
|
7227
|
+
var TYPERT_REMOTE_SEGMENT_PATTERN = /^[A-Za-z0-9_$.-]+$/;
|
|
7228
|
+
function isTypertRemoteSegment(value) {
|
|
7229
|
+
return value !== "." && value !== ".." && TYPERT_REMOTE_SEGMENT_PATTERN.test(value);
|
|
7230
|
+
}
|
|
7231
|
+
var REMOTE_METHOD_DESCRIPTOR = "@deepseek-ai/dsh-typert-protocol/remote-methods";
|
|
7232
|
+
function bindTypertRemote(service, serviceKey, options = {}) {
|
|
7233
|
+
validateName("service key", serviceKey);
|
|
7234
|
+
const namespace = options.namespace ?? serviceKey;
|
|
7235
|
+
validateName("namespace", namespace);
|
|
7236
|
+
return Object.freeze({
|
|
7237
|
+
service,
|
|
7238
|
+
serviceKey,
|
|
7239
|
+
namespace
|
|
7240
|
+
});
|
|
7241
|
+
}
|
|
7242
|
+
var TypertRemoteService = class extends Service {
|
|
7243
|
+
/** Visible binding consumed by the Gateway's source-mode discovery. */
|
|
7244
|
+
typertRemote;
|
|
7245
|
+
/**
|
|
7246
|
+
* Register the Service and bind the same key to Typert Gateway.
|
|
7247
|
+
* @param ctx - owning Cordis Context.
|
|
7248
|
+
* @param serviceKey - exact Cordis service key and default wire namespace.
|
|
7249
|
+
* @param options - optional distinct wire namespace.
|
|
7250
|
+
*/
|
|
7251
|
+
constructor(ctx, serviceKey, options = {}) {
|
|
7252
|
+
super(ctx, serviceKey);
|
|
7253
|
+
this.typertRemote = bindTypertRemote(this, this.name, options);
|
|
7254
|
+
}
|
|
7255
|
+
};
|
|
7256
|
+
function Remote(methodExportOrOptions, context) {
|
|
7257
|
+
if (typeof methodExportOrOptions === "string") {
|
|
7258
|
+
validateName("Remote export name", methodExportOrOptions);
|
|
7259
|
+
return remoteDecorator({ kind: "direct" }, void 0, methodExportOrOptions);
|
|
7260
|
+
}
|
|
7261
|
+
if (typeof methodExportOrOptions === "object") {
|
|
7262
|
+
if (remoteOptionMode(methodExportOrOptions) !== "stream" || Reflect.ownKeys(methodExportOrOptions).length !== 1) throw new TypeError('typert-protocol: Remote options must contain exactly mode: "stream"');
|
|
7263
|
+
return remoteDecorator({ kind: "direct" }, "stream");
|
|
7264
|
+
}
|
|
7265
|
+
if (context === void 0) throw new TypeError("typert-protocol: Remote decorator context is missing");
|
|
7266
|
+
addMarkerInitializer(context, { kind: "direct" });
|
|
7267
|
+
}
|
|
7268
|
+
function remoteOptionMode(options) {
|
|
7269
|
+
return Reflect.get(options, "mode");
|
|
7270
|
+
}
|
|
7271
|
+
function remoteDecorator(invocation, mode, exportName) {
|
|
7272
|
+
return function(_method, context) {
|
|
7273
|
+
addMarkerInitializer(context, invocation, mode, exportName);
|
|
7274
|
+
};
|
|
7275
|
+
}
|
|
7276
|
+
function readRemoteMethodDescriptor(prototype) {
|
|
7277
|
+
const property2 = Object.getOwnPropertyDescriptor(prototype, REMOTE_METHOD_DESCRIPTOR);
|
|
7278
|
+
if (property2 === void 0) return void 0;
|
|
7279
|
+
const descriptor = property2.value;
|
|
7280
|
+
if (descriptor === null || typeof descriptor !== "object") throw new TypeError("typert-protocol: Remote method descriptor must be an object");
|
|
7281
|
+
const version2 = Reflect.get(descriptor, "version");
|
|
7282
|
+
if (version2 !== 1) throw new TypeError(`typert-protocol: unsupported Remote method descriptor version ${String(version2)}`);
|
|
7283
|
+
const methods = Reflect.get(descriptor, "methods");
|
|
7284
|
+
if (!Array.isArray(methods)) throw new TypeError("typert-protocol: Remote method descriptor methods must be an array");
|
|
7285
|
+
return descriptor;
|
|
7286
|
+
}
|
|
7287
|
+
function addMarkerInitializer(context, invocation, mode, exportName) {
|
|
7288
|
+
if (context.private || context.static || typeof context.name !== "string") throw new TypeError("typert-protocol: Remote decorators require a public instance method with a string name");
|
|
7289
|
+
const method = context.name;
|
|
7290
|
+
context.addInitializer(function() {
|
|
7291
|
+
const prototype = Object.getPrototypeOf(this);
|
|
7292
|
+
if (prototype === null) throw new TypeError(`typert-protocol: cannot mark Remote method "${method}" on an object without a prototype`);
|
|
7293
|
+
mark(prototype, method, invocation, mode, exportName);
|
|
7294
|
+
});
|
|
7295
|
+
}
|
|
7296
|
+
function mark(prototype, method, invocation, mode, exportName) {
|
|
7297
|
+
const descriptor = readRemoteMethodDescriptor(prototype);
|
|
7298
|
+
const marker = Object.freeze({
|
|
7299
|
+
method,
|
|
7300
|
+
...exportName === void 0 || exportName === method ? {} : { exportName },
|
|
7301
|
+
...mode === void 0 ? {} : { mode },
|
|
7302
|
+
invocation: Object.freeze(invocation)
|
|
7303
|
+
});
|
|
7304
|
+
const current = descriptor?.methods.find((candidate) => candidate.method === method);
|
|
7305
|
+
if (current !== void 0) {
|
|
7306
|
+
if (current.exportName === marker.exportName && current.mode === marker.mode && sameInvocation(current.invocation, invocation)) return;
|
|
7307
|
+
throw new Error(`typert-protocol: Remote method "${method}" has conflicting invocation markers`);
|
|
7308
|
+
}
|
|
7309
|
+
Object.defineProperty(prototype, REMOTE_METHOD_DESCRIPTOR, {
|
|
7310
|
+
configurable: true,
|
|
7311
|
+
value: Object.freeze({
|
|
7312
|
+
version: 1,
|
|
7313
|
+
methods: Object.freeze([...descriptor?.methods ?? [], marker])
|
|
7314
|
+
})
|
|
7315
|
+
});
|
|
7316
|
+
}
|
|
7317
|
+
function sameInvocation(left, right) {
|
|
7318
|
+
if (left.kind === "direct") return right.kind === "direct";
|
|
7319
|
+
if (right.kind === "direct") return false;
|
|
7320
|
+
return left.context === right.context;
|
|
7321
|
+
}
|
|
7322
|
+
function validateName(subject, value) {
|
|
7323
|
+
if (!isTypertRemoteSegment(value)) throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`);
|
|
7324
|
+
}
|
|
7325
|
+
|
|
7326
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-timeout@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-timeout/lib/index.js
|
|
7327
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
7328
|
+
|
|
7329
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-llm@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-llm/lib/index.js
|
|
7330
|
+
function freezeMessage(message) {
|
|
7331
|
+
return deepFreeze(structuredClone(message));
|
|
7332
|
+
}
|
|
7333
|
+
var HarnessError = class extends Error {
|
|
7334
|
+
/** Stable machine-routable failure class (e.g. `RATE_LIMIT`); route on this, never by parsing `message`. */
|
|
7335
|
+
code;
|
|
7336
|
+
constructor(message, code, options) {
|
|
7337
|
+
super(message, options);
|
|
7338
|
+
this.code = code;
|
|
7339
|
+
this.name = new.target.name;
|
|
7340
|
+
}
|
|
7341
|
+
};
|
|
7342
|
+
var EMPTY_RESPONSE_CODE = "EMPTY_RESPONSE";
|
|
7343
|
+
var STRUCTURED_CONTEXT_OVERFLOW = new RegExp(String.raw`(?:^|[^a-z0-9])context[\s_-](?:length|window)[\s_-]` + String.raw`(?:exceed(?:ed|s)?|overflow(?:ed)?|limit[\s_-]exceeded)(?:$|[^a-z0-9])`, "i");
|
|
7344
|
+
var TOO_LARGE_FOR_CONTEXT = new RegExp(String.raw`\b(?:request|prompt|input|messages?)\s+(?:is\s+|are\s+)?` + String.raw`too\s+(?:large|long)\s+for\s+(?:(?:this|the)\s+)?` + String.raw`(?:model(?:'s)?\s+)?context(?:\s+window)?\b`, "i");
|
|
7345
|
+
var EXCEEDS_MODEL_CONTEXT = new RegExp(String.raw`\b(?:input|prompt|request|messages?)\b.{0,40}` + String.raw`\b(?:exceed(?:s|ed)?|overflows?|is\s+larger\s+than)\b.{0,40}` + String.raw`\b(?:the\s+)?(?:model(?:'s)?\s+)?context(?:\s+(?:length|window))?\b`, "i");
|
|
7346
|
+
var DEFAULT_MAX_RETRIES = 5;
|
|
7347
|
+
var DEFAULT_INITIAL_DELAY_MS = 500;
|
|
7348
|
+
var DEFAULT_MAX_DELAY_MS = 1e4;
|
|
7349
|
+
var DEFAULT_JITTER_RATIO = 0.1;
|
|
7350
|
+
var DEFAULT_RETRYABLE_CODES = Object.freeze([
|
|
7351
|
+
EMPTY_RESPONSE_CODE,
|
|
7352
|
+
"RATE_LIMIT",
|
|
7353
|
+
"SERVER",
|
|
7354
|
+
"TIMEOUT",
|
|
7355
|
+
"TRANSPORT"
|
|
7356
|
+
]);
|
|
7357
|
+
var backoffSchema = Schema.object({
|
|
7358
|
+
initialDelayMs: Schema.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_INITIAL_DELAY_MS),
|
|
7359
|
+
maxDelayMs: Schema.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_MAX_DELAY_MS),
|
|
7360
|
+
jitterRatio: Schema.number().min(0).max(1).default(DEFAULT_JITTER_RATIO)
|
|
7361
|
+
});
|
|
7362
|
+
var normalPolicySchema = Schema.object({
|
|
7363
|
+
mode: Schema.const("normal").required(),
|
|
7364
|
+
maxRetries: Schema.number().step(1).min(0).max(Number.MAX_SAFE_INTEGER).default(DEFAULT_MAX_RETRIES),
|
|
7365
|
+
retryableCodes: Schema.array(Schema.string()).default([...DEFAULT_RETRYABLE_CODES]),
|
|
7366
|
+
backoff: backoffSchema
|
|
7367
|
+
});
|
|
7368
|
+
var alwaysPolicySchema = Schema.object({
|
|
7369
|
+
mode: Schema.const("always").required(),
|
|
7370
|
+
backoff: backoffSchema
|
|
7371
|
+
});
|
|
7372
|
+
var RetryPolicySchema = Schema.union([normalPolicySchema, alwaysPolicySchema]);
|
|
7373
|
+
var NORMAL_POLICY_KEYS = /* @__PURE__ */ new Set([
|
|
7374
|
+
"mode",
|
|
7375
|
+
"maxRetries",
|
|
7376
|
+
"retryableCodes",
|
|
7377
|
+
"backoff"
|
|
7378
|
+
]);
|
|
7379
|
+
var ALWAYS_POLICY_KEYS = /* @__PURE__ */ new Set([
|
|
7380
|
+
"mode",
|
|
7381
|
+
"maxRetries",
|
|
7382
|
+
"retryableCodes",
|
|
7383
|
+
"backoff"
|
|
7384
|
+
]);
|
|
7385
|
+
var BACKOFF_KEYS = /* @__PURE__ */ new Set([
|
|
7386
|
+
"initialDelayMs",
|
|
7387
|
+
"maxDelayMs",
|
|
7388
|
+
"jitterRatio"
|
|
7389
|
+
]);
|
|
7390
|
+
function validateKeys(value, allowed, path) {
|
|
7391
|
+
for (const key of Object.keys(value)) if (!allowed.has(key)) throw new Error(`${path}: unknown key "${key}"`);
|
|
7392
|
+
}
|
|
7393
|
+
function resolveBackoff(config, path) {
|
|
7394
|
+
if (config !== void 0) validateKeys(config, BACKOFF_KEYS, path);
|
|
7395
|
+
const initialDelayMs = config?.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
|
|
7396
|
+
const maxDelayMs = config?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
7397
|
+
const jitterRatio = config?.jitterRatio ?? DEFAULT_JITTER_RATIO;
|
|
7398
|
+
if (!Number.isFinite(initialDelayMs) || initialDelayMs <= 0 || initialDelayMs > MAX_TIMER_DELAY_MS) throw new Error(`${path}.initialDelayMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
|
|
7399
|
+
if (!Number.isFinite(maxDelayMs) || maxDelayMs <= 0 || maxDelayMs > MAX_TIMER_DELAY_MS) throw new Error(`${path}.maxDelayMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
|
|
7400
|
+
if (initialDelayMs > maxDelayMs) throw new Error(`${path}.initialDelayMs must be less than or equal to maxDelayMs`);
|
|
7401
|
+
if (!Number.isFinite(jitterRatio) || jitterRatio < 0 || jitterRatio > 1) throw new Error(`${path}.jitterRatio must be between 0 and 1`);
|
|
7402
|
+
return Object.freeze({
|
|
7403
|
+
initialDelayMs,
|
|
7404
|
+
maxDelayMs,
|
|
7405
|
+
jitterRatio
|
|
7406
|
+
});
|
|
7407
|
+
}
|
|
7408
|
+
function resolveRetryPolicy(config, path) {
|
|
7409
|
+
if (config === void 0) return Object.freeze({
|
|
7410
|
+
mode: "normal",
|
|
7411
|
+
maxRetries: DEFAULT_MAX_RETRIES,
|
|
7412
|
+
retryableCodes: DEFAULT_RETRYABLE_CODES,
|
|
7413
|
+
...resolveBackoff(void 0, `${path}.backoff`)
|
|
7414
|
+
});
|
|
7415
|
+
switch (config.mode) {
|
|
7416
|
+
case "normal": {
|
|
7417
|
+
validateKeys(config, NORMAL_POLICY_KEYS, path);
|
|
7418
|
+
const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
7419
|
+
const retryableCodes = config.retryableCodes ?? [...DEFAULT_RETRYABLE_CODES];
|
|
7420
|
+
if (!Number.isSafeInteger(maxRetries) || maxRetries < 0) throw new Error(`${path}.maxRetries must be a non-negative safe integer`);
|
|
7421
|
+
if (retryableCodes.length === 0) throw new Error(`${path}.retryableCodes must not be empty`);
|
|
7422
|
+
if (retryableCodes.some((code) => typeof code !== "string" || code.length === 0)) throw new Error(`${path}.retryableCodes must contain only non-empty strings`);
|
|
7423
|
+
if (new Set(retryableCodes).size !== retryableCodes.length) throw new Error(`${path}.retryableCodes must not contain duplicates`);
|
|
7424
|
+
return Object.freeze({
|
|
7425
|
+
mode: "normal",
|
|
7426
|
+
maxRetries,
|
|
7427
|
+
retryableCodes: Object.freeze([...retryableCodes]),
|
|
7428
|
+
...resolveBackoff(config.backoff, `${path}.backoff`)
|
|
7429
|
+
});
|
|
7430
|
+
}
|
|
7431
|
+
case "always":
|
|
7432
|
+
validateKeys(config, ALWAYS_POLICY_KEYS, path);
|
|
7433
|
+
return Object.freeze({
|
|
7434
|
+
mode: "always",
|
|
7435
|
+
...resolveBackoff(config.backoff, `${path}.backoff`)
|
|
7436
|
+
});
|
|
7437
|
+
default:
|
|
7438
|
+
throw new Error(`${path}.mode must be "normal" or "always"`);
|
|
7439
|
+
}
|
|
7440
|
+
}
|
|
7441
|
+
function callConfigEquals(a, b) {
|
|
7442
|
+
if (a.provider !== b.provider || a.model !== b.model || a.reasoningEffort !== b.reasoningEffort || a.temperature !== b.temperature || a.maxTokens !== b.maxTokens) return false;
|
|
7443
|
+
if (a.stop === void 0 || b.stop === void 0) return a.stop === b.stop;
|
|
7444
|
+
return a.stop.length === b.stop.length && a.stop.every((s, i) => s === b.stop?.[i]);
|
|
7445
|
+
}
|
|
7446
|
+
function normalizeLlmFailure(value) {
|
|
7447
|
+
const error = value instanceof Error ? value : new HarnessError(thrownMessage(value), "UNKNOWN", { cause: value });
|
|
7448
|
+
const carried = ownFailureSnapshot(error);
|
|
7449
|
+
if (carried !== void 0 && carried.code === ownErrorCode(error)) return carried;
|
|
7450
|
+
return Object.freeze({
|
|
7451
|
+
message: errorMessage(error),
|
|
7452
|
+
code: harnessErrorCode(error)
|
|
7453
|
+
});
|
|
7454
|
+
}
|
|
7455
|
+
function thrownMessage(value) {
|
|
7456
|
+
try {
|
|
7457
|
+
const message = String(value);
|
|
7458
|
+
return message.length > 0 ? message : "LLM adapter failed";
|
|
7459
|
+
} catch (_hostileThrownValue) {
|
|
7460
|
+
return "LLM adapter failed";
|
|
7461
|
+
}
|
|
7462
|
+
}
|
|
7463
|
+
function ownErrorCode(error) {
|
|
7464
|
+
try {
|
|
7465
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, "code");
|
|
7466
|
+
return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
|
|
7467
|
+
} catch (_sdkPropertyTrap) {
|
|
7468
|
+
return;
|
|
7469
|
+
}
|
|
7470
|
+
}
|
|
7471
|
+
function ownFailureSnapshot(error) {
|
|
7472
|
+
try {
|
|
7473
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, "failure");
|
|
7474
|
+
return descriptor !== void 0 && "value" in descriptor ? failureSnapshot(descriptor.value) : void 0;
|
|
7475
|
+
} catch (_sdkPropertyTrap) {
|
|
7476
|
+
return;
|
|
7477
|
+
}
|
|
7478
|
+
}
|
|
7479
|
+
function failureSnapshot(value) {
|
|
7480
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7481
|
+
try {
|
|
7482
|
+
const candidate = value;
|
|
7483
|
+
const message = candidate.message;
|
|
7484
|
+
const code = candidate.code;
|
|
7485
|
+
const status = candidate.status;
|
|
7486
|
+
const providerRetryAfterMs = candidate.providerRetryAfterMs;
|
|
7487
|
+
const requestId = candidate.requestId;
|
|
7488
|
+
if (typeof message !== "string" || message.length === 0 || typeof code !== "string" || code.length === 0 || status !== void 0 && (!Number.isInteger(status) || status < 100 || status > 599) || providerRetryAfterMs !== void 0 && (!Number.isFinite(providerRetryAfterMs) || providerRetryAfterMs <= 0) || requestId !== void 0 && (typeof requestId !== "string" || requestId.length === 0)) return void 0;
|
|
7489
|
+
return Object.freeze({
|
|
7490
|
+
message,
|
|
7491
|
+
code,
|
|
7492
|
+
...status === void 0 ? {} : { status },
|
|
7493
|
+
...providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs },
|
|
7494
|
+
...requestId === void 0 ? {} : { requestId }
|
|
7495
|
+
});
|
|
7496
|
+
} catch (_sdkFailureGetter) {
|
|
7497
|
+
return;
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
function errorMessage(error) {
|
|
7501
|
+
try {
|
|
7502
|
+
const message = error.message;
|
|
7503
|
+
if (typeof message === "string" && message.length > 0) return message;
|
|
7504
|
+
} catch (_sdkMessageGetter) {
|
|
7505
|
+
}
|
|
7506
|
+
return "LLM adapter failed";
|
|
7507
|
+
}
|
|
7508
|
+
function harnessErrorCode(error) {
|
|
7509
|
+
return error instanceof HarnessError ? error.code : "UNKNOWN";
|
|
7510
|
+
}
|
|
7511
|
+
function quoted(value) {
|
|
7512
|
+
return JSON.stringify(value);
|
|
7513
|
+
}
|
|
7514
|
+
function textOnlyImageText(ref) {
|
|
7515
|
+
return `[image omitted because this model accepts text only; attachment sha256:${String(ref.attachmentId).slice(7, 15)}]`;
|
|
7516
|
+
}
|
|
7517
|
+
function contentHasImage(content) {
|
|
7518
|
+
return content.some((block) => block.type === "image" || block.type === "tool-result" && contentHasImage(block.content));
|
|
7519
|
+
}
|
|
7520
|
+
function contentHasFile(content) {
|
|
7521
|
+
for (const block of content) if (block.type === "file" || block.type === "tool-result" && contentHasFile(block.content)) return true;
|
|
7522
|
+
return false;
|
|
7523
|
+
}
|
|
7524
|
+
function fileHandleText(ref, readonlyPath) {
|
|
7525
|
+
const digest = String(ref.attachmentId).slice(7, 15);
|
|
7526
|
+
const identity = `File ${quoted(ref.name)} (${ref.bytes} bytes, sha256:${digest})`;
|
|
7527
|
+
if (readonlyPath === void 0) return `[${identity} was uploaded, but the current execution environment cannot access a readable path. Report that limitation if its contents are needed; do not claim to have read it.]`;
|
|
7528
|
+
return `[${identity}: verbatim read-only copy saved at ${quoted(readonlyPath)}. Read that path with your file tools when its contents are needed; copy it to a writable location before modifying it. When delegating file work, include this saved path in the delegation prompt; only subagents sharing this execution environment can read it.]`;
|
|
7529
|
+
}
|
|
7530
|
+
function replaceFilesWithHandles(blocks, resolvePath) {
|
|
7531
|
+
let next;
|
|
7532
|
+
for (const [index, block] of blocks.entries()) {
|
|
7533
|
+
if (block.type === "file") {
|
|
7534
|
+
next ??= blocks.slice(0, index);
|
|
7535
|
+
next.push({
|
|
7536
|
+
type: "text",
|
|
7537
|
+
text: fileHandleText(block.attachment, resolvePath(block.attachment))
|
|
7538
|
+
});
|
|
7539
|
+
continue;
|
|
7540
|
+
}
|
|
7541
|
+
if (block.type === "tool-result") {
|
|
7542
|
+
const content = replaceFilesWithHandles(block.content, resolvePath);
|
|
7543
|
+
if (content !== block.content) {
|
|
7544
|
+
next ??= blocks.slice(0, index);
|
|
7545
|
+
next.push({
|
|
7546
|
+
...block,
|
|
7547
|
+
content
|
|
7548
|
+
});
|
|
7549
|
+
continue;
|
|
7550
|
+
}
|
|
7551
|
+
}
|
|
7552
|
+
next?.push(block);
|
|
7553
|
+
}
|
|
7554
|
+
return next ?? blocks;
|
|
7555
|
+
}
|
|
7556
|
+
function projectFilesToText(messages, resolvePath) {
|
|
7557
|
+
if (!messages.some((message) => contentHasFile(message.content))) return messages;
|
|
7558
|
+
return messages.map((message) => {
|
|
7559
|
+
const content = replaceFilesWithHandles(message.content, resolvePath);
|
|
7560
|
+
return content === message.content ? message : {
|
|
7561
|
+
...message,
|
|
7562
|
+
content
|
|
7563
|
+
};
|
|
7564
|
+
});
|
|
7565
|
+
}
|
|
7566
|
+
function replaceImagesForTextModel(blocks) {
|
|
7567
|
+
let next;
|
|
7568
|
+
for (const [index, block] of blocks.entries()) {
|
|
7569
|
+
if (block.type === "image") {
|
|
7570
|
+
next ??= blocks.slice(0, index);
|
|
7571
|
+
next.push({
|
|
7572
|
+
type: "text",
|
|
7573
|
+
text: textOnlyImageText(block.attachment)
|
|
7574
|
+
});
|
|
7575
|
+
continue;
|
|
7576
|
+
}
|
|
7577
|
+
if (block.type === "tool-result") {
|
|
7578
|
+
const content = replaceImagesForTextModel(block.content);
|
|
7579
|
+
if (content !== block.content) {
|
|
7580
|
+
next ??= blocks.slice(0, index);
|
|
7581
|
+
next.push({
|
|
7582
|
+
...block,
|
|
7583
|
+
content
|
|
7584
|
+
});
|
|
7585
|
+
continue;
|
|
7586
|
+
}
|
|
7587
|
+
}
|
|
7588
|
+
next?.push(block);
|
|
7589
|
+
}
|
|
7590
|
+
return next ?? blocks;
|
|
7591
|
+
}
|
|
7592
|
+
function projectImagesForTextModel(messages) {
|
|
7593
|
+
if (!messages.some((message) => contentHasImage(message.content))) return messages;
|
|
7594
|
+
return messages.map((message) => {
|
|
7595
|
+
const content = replaceImagesForTextModel(message.content);
|
|
7596
|
+
return content === message.content ? message : {
|
|
7597
|
+
...message,
|
|
7598
|
+
content
|
|
7599
|
+
};
|
|
7600
|
+
});
|
|
7601
|
+
}
|
|
7602
|
+
var { version } = createRequire(import.meta.url)("../package.json");
|
|
7603
|
+
var __runInitializers = function(thisArg, initializers, value) {
|
|
7604
|
+
var useValue = arguments.length > 2;
|
|
7605
|
+
for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
7606
|
+
return useValue ? value : void 0;
|
|
7607
|
+
};
|
|
7608
|
+
var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
7609
|
+
function accept(f) {
|
|
7610
|
+
if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
|
|
7611
|
+
return f;
|
|
7612
|
+
}
|
|
7613
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
7614
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
7615
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
7616
|
+
var _, done = false;
|
|
7617
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
7618
|
+
var context = {};
|
|
7619
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
7620
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
7621
|
+
context.addInitializer = function(f) {
|
|
7622
|
+
if (done) throw new TypeError("Cannot add initializers after decoration has completed");
|
|
7623
|
+
extraInitializers.push(accept(f || null));
|
|
7624
|
+
};
|
|
7625
|
+
var result = (0, decorators[i])(kind === "accessor" ? {
|
|
7626
|
+
get: descriptor.get,
|
|
7627
|
+
set: descriptor.set
|
|
7628
|
+
} : descriptor[key], context);
|
|
7629
|
+
if (kind === "accessor") {
|
|
7630
|
+
if (result === void 0) continue;
|
|
7631
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
7632
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
7633
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
7634
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
7635
|
+
} else if (_ = accept(result)) if (kind === "field") initializers.unshift(_);
|
|
7636
|
+
else descriptor[key] = _;
|
|
7637
|
+
}
|
|
7638
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
7639
|
+
done = true;
|
|
7640
|
+
};
|
|
7641
|
+
var LlmError = class extends HarnessError {
|
|
7642
|
+
/** Serializable facts retained beside this live Error. */
|
|
7643
|
+
failure;
|
|
7644
|
+
/**
|
|
7645
|
+
* @param message - non-empty human-readable failure summary.
|
|
7646
|
+
* @param code - non-empty stable provider-neutral machine code.
|
|
7647
|
+
* @param options - optional cause and validated serializable provider facts.
|
|
7648
|
+
*/
|
|
7649
|
+
constructor(message, code, options) {
|
|
7650
|
+
if (typeof message !== "string" || message.length === 0) throw new Error("LlmError message must be a non-empty string");
|
|
7651
|
+
if (typeof code !== "string" || code.length === 0) throw new Error("LlmError code must be a non-empty string");
|
|
7652
|
+
if (options?.status !== void 0 && (!Number.isInteger(options.status) || options.status < 100 || options.status > 599)) throw new Error("LlmError status must be an integer from 100 through 599");
|
|
7653
|
+
if (options?.providerRetryAfterMs !== void 0 && (!Number.isFinite(options.providerRetryAfterMs) || options.providerRetryAfterMs <= 0)) throw new Error("LlmError providerRetryAfterMs must be a positive finite number");
|
|
7654
|
+
if (options?.requestId !== void 0 && (typeof options.requestId !== "string" || options.requestId.length === 0)) throw new Error("LlmError requestId must be a non-empty string");
|
|
7655
|
+
super(message, code, options);
|
|
7656
|
+
this.name = "LlmError";
|
|
7657
|
+
this.failure = Object.freeze({
|
|
7658
|
+
message,
|
|
7659
|
+
code,
|
|
7660
|
+
...options?.status === void 0 ? {} : { status: options.status },
|
|
7661
|
+
...options?.providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs: options.providerRetryAfterMs },
|
|
7662
|
+
...options?.requestId === void 0 ? {} : { requestId: options.requestId }
|
|
7663
|
+
});
|
|
7664
|
+
}
|
|
7665
|
+
};
|
|
7666
|
+
var LlmRuntime = (() => {
|
|
7667
|
+
let _classSuper = TypertRemoteService;
|
|
7668
|
+
let _instanceExtraInitializers = [];
|
|
7669
|
+
let _listProviders_decorators;
|
|
7670
|
+
let _listConfigurableProviders_decorators;
|
|
7671
|
+
let _remoteDiscoverModels_decorators;
|
|
7672
|
+
return class LlmRuntime extends _classSuper {
|
|
7673
|
+
static {
|
|
7674
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
7675
|
+
_listProviders_decorators = [Remote];
|
|
7676
|
+
_listConfigurableProviders_decorators = [Remote];
|
|
7677
|
+
_remoteDiscoverModels_decorators = [Remote("discoverModels")];
|
|
7678
|
+
__esDecorate(this, null, _listProviders_decorators, {
|
|
7679
|
+
kind: "method",
|
|
7680
|
+
name: "listProviders",
|
|
7681
|
+
static: false,
|
|
7682
|
+
private: false,
|
|
7683
|
+
access: {
|
|
7684
|
+
has: (obj) => "listProviders" in obj,
|
|
7685
|
+
get: (obj) => obj.listProviders
|
|
7686
|
+
},
|
|
7687
|
+
metadata: _metadata
|
|
7688
|
+
}, null, _instanceExtraInitializers);
|
|
7689
|
+
__esDecorate(this, null, _listConfigurableProviders_decorators, {
|
|
7690
|
+
kind: "method",
|
|
7691
|
+
name: "listConfigurableProviders",
|
|
7692
|
+
static: false,
|
|
7693
|
+
private: false,
|
|
7694
|
+
access: {
|
|
7695
|
+
has: (obj) => "listConfigurableProviders" in obj,
|
|
7696
|
+
get: (obj) => obj.listConfigurableProviders
|
|
7697
|
+
},
|
|
7698
|
+
metadata: _metadata
|
|
7699
|
+
}, null, _instanceExtraInitializers);
|
|
7700
|
+
__esDecorate(this, null, _remoteDiscoverModels_decorators, {
|
|
7701
|
+
kind: "method",
|
|
7702
|
+
name: "remoteDiscoverModels",
|
|
7703
|
+
static: false,
|
|
7704
|
+
private: false,
|
|
7705
|
+
access: {
|
|
7706
|
+
has: (obj) => "remoteDiscoverModels" in obj,
|
|
7707
|
+
get: (obj) => obj.remoteDiscoverModels
|
|
7708
|
+
},
|
|
7709
|
+
metadata: _metadata
|
|
7710
|
+
}, null, _instanceExtraInitializers);
|
|
7711
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
7712
|
+
enumerable: true,
|
|
7713
|
+
configurable: true,
|
|
7714
|
+
writable: true,
|
|
7715
|
+
value: _metadata
|
|
7716
|
+
});
|
|
7717
|
+
}
|
|
7718
|
+
adapters = (__runInitializers(this, _instanceExtraInitializers), /* @__PURE__ */ new Map());
|
|
7719
|
+
directory = /* @__PURE__ */ new Map();
|
|
7720
|
+
discoveries = /* @__PURE__ */ new Map();
|
|
7721
|
+
constructor(ctx) {
|
|
7722
|
+
super(ctx, "llm");
|
|
7723
|
+
}
|
|
7724
|
+
/** Notify topology observers without letting one broken listener veto the commit. */
|
|
7725
|
+
emitAdaptersUpdated() {
|
|
7726
|
+
let invariantFailure;
|
|
7727
|
+
for (const listener of this.ctx.events.dispatch("emit", ["llm/adapters-updated"])) try {
|
|
7728
|
+
const returned = listener();
|
|
7729
|
+
if (returned != null && typeof returned.then === "function") Promise.resolve(returned).then(void 0, (error) => {
|
|
7730
|
+
this.warnAdaptersListenerFailure(error);
|
|
7731
|
+
});
|
|
7732
|
+
} catch (error) {
|
|
7733
|
+
if (error?.code === "INVARIANT") {
|
|
7734
|
+
invariantFailure ??= error;
|
|
7735
|
+
continue;
|
|
7736
|
+
}
|
|
7737
|
+
this.warnAdaptersListenerFailure(error);
|
|
7738
|
+
}
|
|
7739
|
+
if (invariantFailure !== void 0) throw invariantFailure;
|
|
7740
|
+
}
|
|
7741
|
+
/** Contained-listener diagnostic shared by the sync and async failure paths. */
|
|
7742
|
+
warnAdaptersListenerFailure(error) {
|
|
7743
|
+
this.ctx.logger.warn("llm: an llm/adapters-updated listener failed");
|
|
7744
|
+
this.ctx.logger.warn(error);
|
|
7745
|
+
}
|
|
7746
|
+
/**
|
|
7747
|
+
* Register an adapter for the given provider routes. Throws `LlmError` with code
|
|
7748
|
+
* `DUPLICATE_ADAPTER` if any provider already has an adapter (all-or-nothing).
|
|
7749
|
+
* Disposed with the fiber.
|
|
7750
|
+
* @param providers - every provider route this adapter should serve.
|
|
7751
|
+
* @param adapter - the adapter that streams calls for those providers.
|
|
7752
|
+
* @returns the disposer, carrying {@link AdapterRegistrationHandle.replace}.
|
|
7753
|
+
*/
|
|
7754
|
+
registerAdapter(providers, adapter) {
|
|
7755
|
+
const owned = /* @__PURE__ */ new Set();
|
|
7756
|
+
let released = false;
|
|
7757
|
+
const dispose = this.ctx.effect(function* () {
|
|
7758
|
+
if (providers.length === 0) throw new LlmError("an adapter must register at least one provider", "INVALID_ADAPTER");
|
|
7759
|
+
this.commitRoutes(owned, this.prepareRoutes(providers, adapter, owned));
|
|
7760
|
+
yield () => {
|
|
7761
|
+
released = true;
|
|
7762
|
+
for (const provider of owned) this.adapters.delete(provider);
|
|
7763
|
+
owned.clear();
|
|
7764
|
+
this.emitAdaptersUpdated();
|
|
7765
|
+
};
|
|
7766
|
+
}.bind(this), "llm.registerAdapter()");
|
|
7767
|
+
const handle = () => void dispose();
|
|
7768
|
+
handle.replace = (next) => {
|
|
7769
|
+
if (released) throw new LlmError("a disposed adapter registration cannot replace its routes", "REGISTRATION_DISPOSED");
|
|
7770
|
+
this.commitRoutes(owned, this.prepareRoutes(next, adapter, owned));
|
|
7771
|
+
};
|
|
7772
|
+
return handle;
|
|
7773
|
+
}
|
|
7774
|
+
/**
|
|
7775
|
+
* Validate one candidate route set for `adapter`, treating routes this
|
|
7776
|
+
* registration already holds as available. Nothing is mutated: a rejected
|
|
7777
|
+
* candidate leaves the registry exactly as it was.
|
|
7778
|
+
*/
|
|
7779
|
+
prepareRoutes(providers, adapter, owned) {
|
|
7780
|
+
const unique = /* @__PURE__ */ new Set();
|
|
7781
|
+
const registrations = [];
|
|
7782
|
+
for (const provider of providers) {
|
|
7783
|
+
if (provider.length === 0) throw new LlmError("adapter provider names must be non-empty", "INVALID_ADAPTER");
|
|
7784
|
+
if (unique.has(provider) || this.adapters.has(provider) && !owned.has(provider)) throw new LlmError(`an adapter for provider "${provider}" is already registered`, "DUPLICATE_ADAPTER");
|
|
7785
|
+
const info = adapter.providerInfo(provider);
|
|
7786
|
+
if (typeof info.id !== "string" || info.id !== provider || typeof info.name !== "string" || info.name.length === 0) throw new LlmError(`adapter metadata for provider "${provider}" must preserve its id and have a non-empty name`, "INVALID_ADAPTER");
|
|
7787
|
+
unique.add(provider);
|
|
7788
|
+
const retryPolicy = adapter.providerRetryPolicy(provider) ?? resolveRetryPolicy(void 0, `llm: provider "${provider}" retryPolicy`);
|
|
7789
|
+
registrations.push({
|
|
7790
|
+
adapter,
|
|
7791
|
+
provider: {
|
|
7792
|
+
id: info.id,
|
|
7793
|
+
name: info.name
|
|
7794
|
+
},
|
|
7795
|
+
retryPolicy
|
|
7796
|
+
});
|
|
7797
|
+
}
|
|
7798
|
+
return registrations;
|
|
7799
|
+
}
|
|
7800
|
+
/**
|
|
7801
|
+
* Swap this registration's routes for the prepared ones in one synchronous
|
|
7802
|
+
* section, so no observer can see the registry between the release and the
|
|
7803
|
+
* re-registration. The route set's one mutation point is also where
|
|
7804
|
+
* `llm/adapters-updated` is published, so a `replace` announces itself
|
|
7805
|
+
* exactly like a first registration.
|
|
7806
|
+
*/
|
|
7807
|
+
commitRoutes(owned, registrations) {
|
|
7808
|
+
for (const provider of owned) this.adapters.delete(provider);
|
|
7809
|
+
owned.clear();
|
|
7810
|
+
for (const registration of registrations) {
|
|
7811
|
+
this.adapters.set(registration.provider.id, registration);
|
|
7812
|
+
owned.add(registration.provider.id);
|
|
7813
|
+
}
|
|
7814
|
+
this.emitAdaptersUpdated();
|
|
7815
|
+
}
|
|
7816
|
+
/**
|
|
7817
|
+
* Describe provider routes with a registered adapter.
|
|
7818
|
+
* @returns detached provider metadata in registration order.
|
|
7819
|
+
*/
|
|
7820
|
+
listProviders() {
|
|
7821
|
+
return [...this.adapters.values()].map(({ provider }) => ({ ...provider }));
|
|
7822
|
+
}
|
|
7823
|
+
/**
|
|
7824
|
+
* Declare provider routes an adapter plugin can activate through
|
|
7825
|
+
* configuration. Registration is all-or-nothing: an empty list, invalid
|
|
7826
|
+
* entry, or a provider already declared by any registration throws
|
|
7827
|
+
* `LlmError` without registering the rest. Disposed with the fiber.
|
|
7828
|
+
* @param entries - every configurable provider this plugin owns.
|
|
7829
|
+
* @returns a handle that withdraws all of them, and can atomically replace them.
|
|
7830
|
+
*/
|
|
7831
|
+
registerConfigurableProviders(entries) {
|
|
7832
|
+
let held = [];
|
|
7833
|
+
let disposed = false;
|
|
7834
|
+
const commit = (candidates) => {
|
|
7835
|
+
const detached = [];
|
|
7836
|
+
const own = new Set(held.map((entry) => entry.provider));
|
|
7837
|
+
for (const entry of candidates) {
|
|
7838
|
+
if (entry.provider.length === 0 || entry.displayName.length === 0 || entry.settingsNs.length === 0) throw new LlmError("configurable providers need a non-empty provider, displayName, and settingsNs", "INVALID_DIRECTORY");
|
|
7839
|
+
if (entry.settingsPath.some((segment) => segment.length === 0)) throw new LlmError(`configurable provider "${entry.provider}" has an empty settingsPath segment`, "INVALID_DIRECTORY");
|
|
7840
|
+
if (this.directory.has(entry.provider) && !own.has(entry.provider) || detached.some((seen) => seen.provider === entry.provider)) throw new LlmError(`configurable provider "${entry.provider}" is already declared`, "DUPLICATE_DIRECTORY");
|
|
7841
|
+
detached.push({
|
|
7842
|
+
...entry,
|
|
7843
|
+
settingsPath: [...entry.settingsPath]
|
|
7844
|
+
});
|
|
7845
|
+
}
|
|
7846
|
+
for (const entry of held) this.directory.delete(entry.provider);
|
|
7847
|
+
for (const entry of detached) this.directory.set(entry.provider, entry);
|
|
7848
|
+
held = detached;
|
|
7849
|
+
this.emitAdaptersUpdated();
|
|
7850
|
+
};
|
|
7851
|
+
const dispose = this.ctx.effect(function* () {
|
|
7852
|
+
if (entries.length === 0) throw new LlmError("a configurable-provider registration must declare at least one provider", "INVALID_DIRECTORY");
|
|
7853
|
+
commit(entries);
|
|
7854
|
+
yield () => {
|
|
7855
|
+
disposed = true;
|
|
7856
|
+
for (const entry of held) this.directory.delete(entry.provider);
|
|
7857
|
+
held = [];
|
|
7858
|
+
this.emitAdaptersUpdated();
|
|
7859
|
+
};
|
|
7860
|
+
}.bind(this), "llm.registerConfigurableProviders()");
|
|
7861
|
+
const handle = () => void dispose();
|
|
7862
|
+
handle.replace = (next) => {
|
|
7863
|
+
if (disposed) throw new LlmError("this configurable-provider registration was disposed", "REGISTRATION_DISPOSED");
|
|
7864
|
+
commit(next);
|
|
7865
|
+
};
|
|
7866
|
+
return handle;
|
|
7867
|
+
}
|
|
7868
|
+
/**
|
|
7869
|
+
* List every declared configurable provider, registered or dormant.
|
|
7870
|
+
* @returns detached directory entries in declaration order.
|
|
7871
|
+
*/
|
|
7872
|
+
listConfigurableProviders() {
|
|
7873
|
+
return [...this.directory.values()].map((entry) => ({
|
|
7874
|
+
...entry,
|
|
7875
|
+
settingsPath: [...entry.settingsPath]
|
|
7876
|
+
}));
|
|
7877
|
+
}
|
|
7878
|
+
/**
|
|
7879
|
+
* Offer to interrogate provider endpoints on behalf of the settings
|
|
7880
|
+
* namespace this plugin owns. The namespace is the key because that is what
|
|
7881
|
+
* a configuration surface already holds from the configurable-provider
|
|
7882
|
+
* directory, and because a provider being *added* has no route to name yet.
|
|
7883
|
+
* Disposed with the fiber.
|
|
7884
|
+
* @param settingsNs - the namespace whose profiles this discovery serves.
|
|
7885
|
+
* @param discover - interrogates one endpoint and must honor the supplied signal.
|
|
7886
|
+
* @returns the disposer that withdraws the offer.
|
|
7887
|
+
*/
|
|
7888
|
+
registerModelDiscovery(settingsNs, discover) {
|
|
7889
|
+
const dispose = this.ctx.effect(function* () {
|
|
7890
|
+
if (settingsNs.length === 0) throw new LlmError("model discovery needs a non-empty settings namespace", "INVALID_DISCOVERY");
|
|
7891
|
+
if (this.discoveries.has(settingsNs)) throw new LlmError(`model discovery for "${settingsNs}" is already registered`, "DUPLICATE_DISCOVERY");
|
|
7892
|
+
this.discoveries.set(settingsNs, discover);
|
|
7893
|
+
yield () => {
|
|
7894
|
+
this.discoveries.delete(settingsNs);
|
|
7895
|
+
};
|
|
7896
|
+
}.bind(this), "llm.registerModelDiscovery()");
|
|
7897
|
+
return () => void dispose();
|
|
7898
|
+
}
|
|
7899
|
+
/**
|
|
7900
|
+
* Interrogate one provider endpoint for the models it advertises. The
|
|
7901
|
+
* request describes a draft, not a stored route, so nothing here reads or
|
|
7902
|
+
* writes settings or credentials — the caller owns both, and the reply is
|
|
7903
|
+
* candidate metadata a surface may offer for adoption.
|
|
7904
|
+
* @param settingsNs - namespace whose registered discovery serves this draft.
|
|
7905
|
+
* @param request - the endpoint, protocol, and one-shot credential to use.
|
|
7906
|
+
* @param signal - caller cancellation.
|
|
7907
|
+
* @returns the advertised models, deduplicated in endpoint order.
|
|
7908
|
+
*/
|
|
7909
|
+
async discoverModels(settingsNs, request, signal) {
|
|
7910
|
+
const discover = this.discoveries.get(settingsNs);
|
|
7911
|
+
if (discover === void 0) throw new LlmError(`no model discovery is registered for "${settingsNs}"`, "NO_DISCOVERY");
|
|
7912
|
+
if ((request.provider ?? "").length === 0 && (request.baseURL ?? "").length === 0) throw new LlmError("model discovery needs a provider route or a baseURL", "INVALID_DISCOVERY");
|
|
7913
|
+
const discovered = signal === void 0 ? await discover(request) : await discover(request, signal);
|
|
7914
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7915
|
+
const models = [];
|
|
7916
|
+
for (const model of discovered) {
|
|
7917
|
+
if (typeof model.id !== "string" || model.id.length === 0 || seen.has(model.id)) continue;
|
|
7918
|
+
seen.add(model.id);
|
|
7919
|
+
models.push({
|
|
7920
|
+
id: model.id,
|
|
7921
|
+
...model.name === void 0 ? {} : { name: model.name },
|
|
7922
|
+
...model.contextWindow === void 0 ? {} : { contextWindow: model.contextWindow },
|
|
7923
|
+
...model.maxTokens === void 0 ? {} : { maxTokens: model.maxTokens }
|
|
7924
|
+
});
|
|
7925
|
+
}
|
|
7926
|
+
return models;
|
|
7927
|
+
}
|
|
7928
|
+
/**
|
|
7929
|
+
* Remote adapter for one draft provider interrogation.
|
|
7930
|
+
* @param settingsNs - namespace whose registered discovery serves this draft.
|
|
7931
|
+
* @param request - endpoint, protocol, and one-shot credential to use.
|
|
7932
|
+
* @param signal - caller cancellation supplied by the Remote carrier.
|
|
7933
|
+
* @returns advertised models in endpoint order.
|
|
7934
|
+
* @throws RemoteError with `llm/model-discovery-rejected` when discovery refuses or fails.
|
|
7935
|
+
*/
|
|
7936
|
+
async remoteDiscoverModels(settingsNs, request, signal) {
|
|
7937
|
+
try {
|
|
7938
|
+
return await this.discoverModels(settingsNs, request, signal);
|
|
7939
|
+
} catch (error) {
|
|
7940
|
+
throw new RemoteError("llm/model-discovery-rejected", error instanceof Error ? error.message : String(error), {
|
|
7941
|
+
settingsNs,
|
|
7942
|
+
...request.baseURL === void 0 ? {} : { baseURL: request.baseURL }
|
|
7943
|
+
}, { cause: error });
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
/**
|
|
7947
|
+
* Resolve the retry policy captured when one provider route was registered.
|
|
7948
|
+
* @param provider - registered provider route to inspect.
|
|
7949
|
+
* @returns the provider-owned policy, with normal defaults already resolved.
|
|
7950
|
+
*/
|
|
7951
|
+
providerRetryPolicy(provider) {
|
|
7952
|
+
return this.registration(provider).retryPolicy;
|
|
7953
|
+
}
|
|
7954
|
+
/**
|
|
7955
|
+
* Resolve provider-side request-image pricing for one exact route, or
|
|
7956
|
+
* `undefined` when the provider is unregistered or declares none. Unknown
|
|
7957
|
+
* providers degrade to `undefined` rather than throwing because callers
|
|
7958
|
+
* price durable history whose route may no longer be mounted.
|
|
7959
|
+
* @param provider - provider route named by a request header.
|
|
7960
|
+
* @param model - exact model id named by the same header.
|
|
7961
|
+
* @returns the owning adapter's image pricing for the route, when declared.
|
|
7962
|
+
*/
|
|
7963
|
+
imageRequestPricing(provider, model) {
|
|
7964
|
+
return this.adapters.get(provider)?.adapter.imageRequestPricing(provider, model);
|
|
7965
|
+
}
|
|
7966
|
+
/**
|
|
7967
|
+
* Resolve the exact text one durable file occurrence contributes to every
|
|
7968
|
+
* provider request in the current execution environment.
|
|
7969
|
+
* @param ref - durable verbatim file reference from model history.
|
|
7970
|
+
* @returns the same deterministic handle text used at adapter dispatch.
|
|
7971
|
+
*/
|
|
7972
|
+
fileRequestText(ref) {
|
|
7973
|
+
return fileHandleText(ref, this.fileReadPath(ref));
|
|
7974
|
+
}
|
|
7975
|
+
/** Detach typed adapter-owned modality metadata. */
|
|
7976
|
+
detachedModalities(modalities) {
|
|
7977
|
+
return modalities === void 0 ? void 0 : [...modalities];
|
|
7978
|
+
}
|
|
7979
|
+
/**
|
|
7980
|
+
* Discover models advertised by one registered provider. Catalog membership
|
|
7981
|
+
* is advisory and never changes routing or request validation.
|
|
7982
|
+
* @param provider - registered provider route to inspect.
|
|
7983
|
+
* @returns detached model metadata in adapter-preferred order.
|
|
7984
|
+
*/
|
|
7985
|
+
async listModels(provider) {
|
|
7986
|
+
const models = await this.registration(provider).adapter.listModels(provider);
|
|
7987
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7988
|
+
return models.map((model) => {
|
|
7989
|
+
if (typeof model.provider !== "string" || model.provider !== provider || typeof model.id !== "string" || model.id.length === 0 || typeof model.name !== "string" || model.name.length === 0 || model.description !== void 0 && typeof model.description !== "string" || seen.has(model.id)) throw new LlmError(`adapter returned invalid or duplicate model metadata for provider "${provider}"`, "INVALID_CATALOG");
|
|
7990
|
+
seen.add(model.id);
|
|
7991
|
+
const inputModalities = this.detachedModalities(model.inputModalities);
|
|
7992
|
+
return {
|
|
7993
|
+
provider: model.provider,
|
|
7994
|
+
id: model.id,
|
|
7995
|
+
name: model.name,
|
|
7996
|
+
...model.description === void 0 ? {} : { description: model.description },
|
|
7997
|
+
...inputModalities === void 0 ? {} : { inputModalities }
|
|
7998
|
+
};
|
|
7999
|
+
});
|
|
8000
|
+
}
|
|
8001
|
+
/**
|
|
8002
|
+
* Resolve and validate all metadata from the adapter that owns one exact
|
|
8003
|
+
* route. The result is detached from adapter-owned objects; catalog
|
|
8004
|
+
* membership remains advisory and does not control request routing.
|
|
8005
|
+
* @param provider - registered provider route to inspect.
|
|
8006
|
+
* @param model - exact model id passed to the adapter.
|
|
8007
|
+
* @param signal - optional cancellation for adapter-owned asynchronous lookup.
|
|
8008
|
+
* @returns exact model identity plus available context and reasoning metadata.
|
|
8009
|
+
*/
|
|
8010
|
+
async resolveModelInfo(provider, model, signal) {
|
|
8011
|
+
return this.resolveModelInfoFor(this.registration(provider), model, signal);
|
|
8012
|
+
}
|
|
8013
|
+
async resolveModelInfoFor(registration, model, signal) {
|
|
8014
|
+
const resolved = await registration.adapter.resolveModel(registration.provider.id, model, signal);
|
|
8015
|
+
return this.normalizeModelInfo(registration, model, resolved);
|
|
8016
|
+
}
|
|
8017
|
+
/** Validate and detach one adapter-returned exact model result. */
|
|
8018
|
+
normalizeModelInfo(registration, model, resolved) {
|
|
8019
|
+
const provider = registration.provider.id;
|
|
8020
|
+
if (typeof resolved.provider !== "string" || resolved.provider !== provider || typeof resolved.id !== "string" || resolved.id !== model || typeof resolved.name !== "string" || resolved.name.length === 0 || resolved.description !== void 0 && typeof resolved.description !== "string") throw new LlmError(`adapter returned invalid exact model metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_INFO");
|
|
8021
|
+
const context = resolved.context;
|
|
8022
|
+
if (context !== void 0 && (!Number.isInteger(context.contextWindow) || context.contextWindow <= 0)) throw new LlmError(`adapter returned invalid context metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_CONTEXT");
|
|
8023
|
+
const inputModalities = this.detachedModalities(resolved.inputModalities);
|
|
8024
|
+
const systemPromptUpdate = resolved.systemPromptUpdate;
|
|
8025
|
+
if (systemPromptUpdate !== void 0 && systemPromptUpdate !== "in-history") throw new LlmError(`adapter returned invalid system prompt update mode for provider "${provider}" model "${model}"`, "INVALID_MODEL_INFO");
|
|
8026
|
+
const defaultMaxTokens = resolved.defaultMaxTokens;
|
|
8027
|
+
if (defaultMaxTokens !== void 0 && (!Number.isSafeInteger(defaultMaxTokens) || defaultMaxTokens <= 0)) throw new LlmError(`adapter returned invalid default maxTokens for provider "${provider}" model "${model}"`, "INVALID_MODEL_MAX_TOKENS");
|
|
8028
|
+
const info = {
|
|
8029
|
+
provider,
|
|
8030
|
+
id: model,
|
|
8031
|
+
name: resolved.name,
|
|
8032
|
+
...resolved.description === void 0 ? {} : { description: resolved.description },
|
|
8033
|
+
...inputModalities === void 0 ? {} : { inputModalities },
|
|
8034
|
+
...context === void 0 ? {} : { context: { contextWindow: context.contextWindow } },
|
|
8035
|
+
...defaultMaxTokens === void 0 ? {} : { defaultMaxTokens },
|
|
8036
|
+
...resolved.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: resolved.systemPromptUpdate }
|
|
8037
|
+
};
|
|
8038
|
+
const reasoning = resolved.reasoning;
|
|
8039
|
+
if (reasoning === void 0) return info;
|
|
8040
|
+
if (reasoning.efforts.length === 0) throw new LlmError(`adapter returned invalid reasoning metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_REASONING");
|
|
8041
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8042
|
+
const efforts = reasoning.efforts.map((effort) => {
|
|
8043
|
+
if (typeof effort.id !== "string" || effort.id.length === 0 || typeof effort.name !== "string" || effort.name.length === 0 || effort.description !== void 0 && typeof effort.description !== "string" || seen.has(effort.id)) throw new LlmError(`adapter returned invalid or duplicate reasoning effort metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_REASONING");
|
|
8044
|
+
seen.add(effort.id);
|
|
8045
|
+
return {
|
|
8046
|
+
id: effort.id,
|
|
8047
|
+
name: effort.name,
|
|
8048
|
+
...effort.description === void 0 ? {} : { description: effort.description }
|
|
8049
|
+
};
|
|
8050
|
+
});
|
|
8051
|
+
if (reasoning.defaultEffort !== void 0 && !seen.has(reasoning.defaultEffort)) throw new LlmError(`adapter returned an unknown default reasoning effort for provider "${provider}" model "${model}"`, "INVALID_MODEL_REASONING");
|
|
8052
|
+
return {
|
|
8053
|
+
...info,
|
|
8054
|
+
reasoning: {
|
|
8055
|
+
efforts,
|
|
8056
|
+
...reasoning.defaultEffort === void 0 ? {} : { defaultEffort: reasoning.defaultEffort }
|
|
8057
|
+
}
|
|
8058
|
+
};
|
|
8059
|
+
}
|
|
8060
|
+
/**
|
|
8061
|
+
* Validate a conversation call config against its exact model capability and
|
|
8062
|
+
* materialize adapter-configured defaults. Unsupported explicit efforts
|
|
8063
|
+
* reject before provider I/O; no clamping or aliasing is performed. This
|
|
8064
|
+
* standalone query does not bind a later dispatch; use {@link prepareCall}
|
|
8065
|
+
* when logging and streaming must share one adapter registration.
|
|
8066
|
+
* @param config - provider/model route and optional request controls.
|
|
8067
|
+
* @param signal - optional cancellation for adapter-owned capability lookup.
|
|
8068
|
+
* @returns a detached config only when a default must be materialized.
|
|
8069
|
+
*/
|
|
8070
|
+
async resolveCallConfig(config, signal) {
|
|
8071
|
+
return (await this.resolveCallFor(this.registration(config.provider), config, signal)).config;
|
|
8072
|
+
}
|
|
8073
|
+
async resolveCallFor(registration, config, signal) {
|
|
8074
|
+
const info = await this.resolveModelInfoFor(registration, config.model, signal);
|
|
8075
|
+
return this.resolveCallWithInfo(config, info);
|
|
8076
|
+
}
|
|
8077
|
+
/** Validate request controls against one already-bound exact model result. */
|
|
8078
|
+
resolveCallWithInfo(config, info) {
|
|
8079
|
+
const defaulted = config.maxTokens === void 0 && info.defaultMaxTokens !== void 0 ? {
|
|
8080
|
+
...config,
|
|
8081
|
+
maxTokens: info.defaultMaxTokens
|
|
8082
|
+
} : config;
|
|
8083
|
+
const reasoning = info.reasoning;
|
|
8084
|
+
const requested = defaulted.reasoningEffort;
|
|
8085
|
+
let resolvedConfig = defaulted;
|
|
8086
|
+
if (reasoning === void 0) {
|
|
8087
|
+
if (requested !== void 0) throw new LlmError(`provider "${config.provider}" model "${config.model}" does not support reasoning effort "${requested}"`, "UNSUPPORTED_REASONING_EFFORT");
|
|
8088
|
+
} else {
|
|
8089
|
+
const effective = requested ?? reasoning.defaultEffort;
|
|
8090
|
+
if (effective !== void 0) {
|
|
8091
|
+
if (!reasoning.efforts.some((effort) => effort.id === effective)) throw new LlmError(`provider "${config.provider}" model "${config.model}" does not support reasoning effort "${effective}"`, "UNSUPPORTED_REASONING_EFFORT");
|
|
8092
|
+
if (requested !== effective) resolvedConfig = {
|
|
8093
|
+
...defaulted,
|
|
8094
|
+
reasoningEffort: effective
|
|
8095
|
+
};
|
|
8096
|
+
}
|
|
8097
|
+
}
|
|
8098
|
+
return {
|
|
8099
|
+
config: resolvedConfig,
|
|
8100
|
+
...info.context === void 0 ? {} : { context: info.context },
|
|
8101
|
+
modelInfo: info
|
|
8102
|
+
};
|
|
8103
|
+
}
|
|
8104
|
+
/**
|
|
8105
|
+
* Resolve one call under its current adapter registration. The returned
|
|
8106
|
+
* one-shot handle keeps that registration across header logging and dispatch,
|
|
8107
|
+
* so HMR cannot combine one adapter's capability result with another adapter.
|
|
8108
|
+
* @param config - provider/model route and optional request controls.
|
|
8109
|
+
* @param signal - optional cancellation for adapter-owned capability lookup.
|
|
8110
|
+
* @returns a prepared config and its registration-bound stream entry point.
|
|
8111
|
+
*/
|
|
8112
|
+
async prepareCall(config, signal) {
|
|
8113
|
+
const registration = this.registration(config.provider);
|
|
8114
|
+
const adapterCall = await registration.adapter.prepareCall(config.provider, config.model, signal);
|
|
8115
|
+
const modelInfo = this.normalizeModelInfo(registration, config.model, adapterCall.model);
|
|
8116
|
+
const resolved = this.resolveCallWithInfo(config, modelInfo);
|
|
8117
|
+
const resolvedConfig = deepFreeze(structuredClone(resolved.config));
|
|
8118
|
+
const context = resolved.context === void 0 ? void 0 : deepFreeze(structuredClone(resolved.context));
|
|
8119
|
+
const adapterDefaults = deepFreeze({
|
|
8120
|
+
...config.reasoningEffort === void 0 && resolvedConfig.reasoningEffort !== void 0 ? { reasoningEffort: true } : {},
|
|
8121
|
+
...config.maxTokens === void 0 && resolvedConfig.maxTokens !== void 0 ? { maxTokens: true } : {}
|
|
8122
|
+
});
|
|
8123
|
+
let dispatched = false;
|
|
8124
|
+
return Object.freeze({
|
|
8125
|
+
config: resolvedConfig,
|
|
8126
|
+
retryPolicy: registration.retryPolicy,
|
|
8127
|
+
adapterDefaults,
|
|
8128
|
+
...context === void 0 ? {} : { context },
|
|
8129
|
+
...modelInfo.inputModalities === void 0 ? {} : { inputModalities: Object.freeze([...modelInfo.inputModalities]) },
|
|
8130
|
+
...modelInfo.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: modelInfo.systemPromptUpdate },
|
|
8131
|
+
stream: (options) => {
|
|
8132
|
+
if (dispatched) throw new LlmError("a prepared LLM call can only be dispatched once", "INVALID_PREPARED_CALL");
|
|
8133
|
+
if (!callConfigEquals(options, resolvedConfig)) throw new LlmError("prepared LLM call config changed before adapter dispatch", "INVALID_PREPARED_CALL");
|
|
8134
|
+
dispatched = true;
|
|
8135
|
+
return this.streamWithRegistration(options, {
|
|
8136
|
+
registration,
|
|
8137
|
+
config: resolvedConfig,
|
|
8138
|
+
modelInfo,
|
|
8139
|
+
dispatch: (options2) => adapterCall.stream(options2)
|
|
8140
|
+
});
|
|
8141
|
+
}
|
|
8142
|
+
});
|
|
8143
|
+
}
|
|
8144
|
+
registration(provider) {
|
|
8145
|
+
const registration = this.adapters.get(provider);
|
|
8146
|
+
if (!registration) throw new LlmError(`no adapter registered for provider "${provider}"`, "NO_ADAPTER");
|
|
8147
|
+
return registration;
|
|
8148
|
+
}
|
|
8149
|
+
/** Remove replay state whose historical route is owned by another adapter. */
|
|
8150
|
+
forAdapter(options, adapter) {
|
|
8151
|
+
const messages = options.messages.map((message) => {
|
|
8152
|
+
const source = message.source;
|
|
8153
|
+
if (message.role !== "assistant" || source.kind !== "model" || source.replayState === void 0) return message;
|
|
8154
|
+
if (this.adapters.get(source.provider)?.adapter === adapter) return message;
|
|
8155
|
+
return freezeMessage({
|
|
8156
|
+
...message,
|
|
8157
|
+
source: {
|
|
8158
|
+
kind: "model",
|
|
8159
|
+
provider: source.provider,
|
|
8160
|
+
model: source.model
|
|
8161
|
+
}
|
|
8162
|
+
});
|
|
8163
|
+
});
|
|
8164
|
+
if (messages.every((message, index) => message === options.messages[index])) return options;
|
|
8165
|
+
const filtered = {
|
|
8166
|
+
...options,
|
|
8167
|
+
messages
|
|
8168
|
+
};
|
|
8169
|
+
return Object.isFrozen(options) ? deepFreeze(filtered) : filtered;
|
|
8170
|
+
}
|
|
8171
|
+
/**
|
|
8172
|
+
* Resolve the current execution-world read path of one durable file
|
|
8173
|
+
* reference through the mounted attachment and filesystem providers.
|
|
8174
|
+
*/
|
|
8175
|
+
fileReadPath(ref) {
|
|
8176
|
+
let hostPath;
|
|
8177
|
+
try {
|
|
8178
|
+
hostPath = this.ctx.get("attachments")?.fileHostPath(ref);
|
|
8179
|
+
} catch {
|
|
8180
|
+
return;
|
|
8181
|
+
}
|
|
8182
|
+
if (hostPath === void 0) return void 0;
|
|
8183
|
+
return this.ctx.get("fs")?.processPathFromHostPath(hostPath);
|
|
8184
|
+
}
|
|
8185
|
+
/**
|
|
8186
|
+
* Final adapter boundary. Adapter selection, dispatch, iterator construction,
|
|
8187
|
+
* and iteration failures become one terminal failure chunk. Middleware and
|
|
8188
|
+
* downstream consumer failures remain thrown plugin or consumer errors.
|
|
8189
|
+
*/
|
|
8190
|
+
async *adapterStream(options, prepared) {
|
|
8191
|
+
let iterator;
|
|
8192
|
+
try {
|
|
8193
|
+
const registration = prepared?.registration ?? this.registration(options.provider);
|
|
8194
|
+
const adapter = registration.adapter;
|
|
8195
|
+
let modelInfo;
|
|
8196
|
+
let resolvedConfig;
|
|
8197
|
+
let dispatch;
|
|
8198
|
+
if (prepared === void 0) {
|
|
8199
|
+
const adapterCall = await adapter.prepareCall(options.provider, options.model, options.signal);
|
|
8200
|
+
modelInfo = this.normalizeModelInfo(registration, options.model, adapterCall.model);
|
|
8201
|
+
resolvedConfig = this.resolveCallWithInfo(options, modelInfo).config;
|
|
8202
|
+
dispatch = (options2) => adapterCall.stream(options2);
|
|
8203
|
+
} else {
|
|
8204
|
+
modelInfo = prepared.modelInfo;
|
|
8205
|
+
resolvedConfig = prepared.config;
|
|
8206
|
+
dispatch = prepared.dispatch;
|
|
8207
|
+
}
|
|
8208
|
+
if (prepared !== void 0 && !callConfigEquals(options, resolvedConfig)) throw new LlmError("prepared LLM call config changed before adapter dispatch", "INVALID_PREPARED_CALL");
|
|
8209
|
+
const resolvedOptions = callConfigEquals(options, resolvedConfig) ? options : Object.isFrozen(options) ? deepFreeze({
|
|
8210
|
+
...options,
|
|
8211
|
+
...resolvedConfig
|
|
8212
|
+
}) : {
|
|
8213
|
+
...options,
|
|
8214
|
+
...resolvedConfig
|
|
8215
|
+
};
|
|
8216
|
+
let projectedMessages = resolvedOptions.messages;
|
|
8217
|
+
if (projectedMessages.some((message) => contentHasFile(message.content))) projectedMessages = projectFilesToText(projectedMessages, (ref) => this.fileReadPath(ref));
|
|
8218
|
+
if (modelInfo.inputModalities !== void 0 && !modelInfo.inputModalities.includes("image") && projectedMessages.some((message) => contentHasImage(message.content))) projectedMessages = projectImagesForTextModel(projectedMessages);
|
|
8219
|
+
const projectedOptions = projectedMessages === resolvedOptions.messages ? resolvedOptions : Object.isFrozen(resolvedOptions) ? deepFreeze({
|
|
8220
|
+
...resolvedOptions,
|
|
8221
|
+
messages: projectedMessages
|
|
8222
|
+
}) : {
|
|
8223
|
+
...resolvedOptions,
|
|
8224
|
+
messages: projectedMessages
|
|
8225
|
+
};
|
|
8226
|
+
iterator = dispatch(this.forAdapter(projectedOptions, adapter))[Symbol.asyncIterator]();
|
|
8227
|
+
} catch (error) {
|
|
8228
|
+
yield adapterFailureChunk(error, options.signal);
|
|
8229
|
+
return;
|
|
8230
|
+
}
|
|
8231
|
+
let completed = false;
|
|
8232
|
+
try {
|
|
8233
|
+
while (true) {
|
|
8234
|
+
let item;
|
|
8235
|
+
try {
|
|
8236
|
+
const next = await iterator.next();
|
|
8237
|
+
item = next.done ? { done: true } : {
|
|
8238
|
+
done: false,
|
|
8239
|
+
value: next.value
|
|
8240
|
+
};
|
|
8241
|
+
} catch (error) {
|
|
8242
|
+
completed = true;
|
|
8243
|
+
yield adapterFailureChunk(error, options.signal);
|
|
8244
|
+
return;
|
|
8245
|
+
}
|
|
8246
|
+
if (item.done) {
|
|
8247
|
+
completed = true;
|
|
8248
|
+
return;
|
|
8249
|
+
}
|
|
8250
|
+
yield item.value;
|
|
8251
|
+
}
|
|
8252
|
+
} finally {
|
|
8253
|
+
if (!completed) {
|
|
8254
|
+
const close = iterator.return?.bind(iterator);
|
|
8255
|
+
if (close) await close();
|
|
8256
|
+
}
|
|
8257
|
+
}
|
|
8258
|
+
}
|
|
8259
|
+
/**
|
|
8260
|
+
* Stream one model call as raw chunks (token-level deltas). Replay state is
|
|
8261
|
+
* retained only when the same adapter instance owns its historical provider
|
|
8262
|
+
* and the target provider. Final adapter selection remains fixed through
|
|
8263
|
+
* asynchronous exact-model resolution and dispatch. Adapter selection,
|
|
8264
|
+
* dispatch, and iteration failures become terminal `error` or `aborted`
|
|
8265
|
+
* finish chunks; middleware, nested-call, cleanup, and consumer failures
|
|
8266
|
+
* remain thrown.
|
|
8267
|
+
* @param options - the full request; `options.provider` selects the adapter.
|
|
8268
|
+
* @returns the chunk stream, possibly wrapped by `llm/stream` listeners.
|
|
8269
|
+
*/
|
|
8270
|
+
stream(options) {
|
|
8271
|
+
return this.streamWithRegistration(options);
|
|
8272
|
+
}
|
|
8273
|
+
streamWithRegistration(options, prepared) {
|
|
8274
|
+
return this.ctx.waterfall(this, "llm/stream", options, () => this.adapterStream(options, prepared));
|
|
8275
|
+
}
|
|
8276
|
+
};
|
|
8277
|
+
})();
|
|
8278
|
+
function adapterFailureChunk(error, signal) {
|
|
8279
|
+
const failure12 = normalizeLlmFailure(error);
|
|
8280
|
+
return {
|
|
8281
|
+
type: "finish",
|
|
8282
|
+
reason: signal?.aborted || failure12.code === "ABORTED" ? {
|
|
8283
|
+
kind: "aborted",
|
|
8284
|
+
failure: failure12
|
|
8285
|
+
} : {
|
|
8286
|
+
kind: "error",
|
|
8287
|
+
failure: failure12
|
|
8288
|
+
}
|
|
8289
|
+
};
|
|
8290
|
+
}
|
|
8291
|
+
|
|
8292
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-web@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2_@deepseek-ai+dsh-llm@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2_/node_modules/@deepseek-ai/dsh-web/lib/index.js
|
|
8293
|
+
var WebError = class extends HarnessError {
|
|
8294
|
+
};
|
|
8295
|
+
var WebRuntime = class extends Service {
|
|
8296
|
+
/**
|
|
8297
|
+
* Provider selection config. Operational env overrides feed the SAME fields:
|
|
8298
|
+
* `$DSH_WEB_SEARCH_PROVIDER` / `$DSH_WEB_FETCH_PROVIDER` are equivalent to
|
|
8299
|
+
* `searchProvider` / `fetchProvider` and are NOT a hidden priority chain.
|
|
8300
|
+
*/
|
|
8301
|
+
static Config = Schema.object({
|
|
8302
|
+
searchProvider: Schema.string(),
|
|
8303
|
+
fetchProvider: Schema.string()
|
|
8304
|
+
});
|
|
8305
|
+
searchProviders = /* @__PURE__ */ new Map();
|
|
8306
|
+
fetchProviders = /* @__PURE__ */ new Map();
|
|
8307
|
+
searchProviderId;
|
|
8308
|
+
fetchProviderId;
|
|
8309
|
+
constructor(ctx, config = {}) {
|
|
8310
|
+
super(ctx, "web");
|
|
8311
|
+
this.searchProviderId = config.searchProvider ?? process.env.DSH_WEB_SEARCH_PROVIDER;
|
|
8312
|
+
this.fetchProviderId = config.fetchProvider ?? process.env.DSH_WEB_FETCH_PROVIDER;
|
|
8313
|
+
}
|
|
8314
|
+
/**
|
|
8315
|
+
* Register a search provider. Throws {@link WebError} `WEB_DUPLICATE_PROVIDER`
|
|
8316
|
+
* if its id is already registered for search. Returns a disposer; disposed
|
|
8317
|
+
* with the calling fiber.
|
|
8318
|
+
* @param provider - the provider; its `id` is the registry key.
|
|
8319
|
+
* @returns the disposer that unregisters the provider.
|
|
8320
|
+
*/
|
|
8321
|
+
registerSearchProvider(provider) {
|
|
8322
|
+
return this.registerProvider(this.searchProviders, provider);
|
|
8323
|
+
}
|
|
8324
|
+
/**
|
|
8325
|
+
* Register a fetch provider. Throws {@link WebError} `WEB_DUPLICATE_PROVIDER`
|
|
8326
|
+
* if its id is already registered for fetch. Returns a disposer; disposed
|
|
8327
|
+
* with the calling fiber.
|
|
8328
|
+
* @param provider - the provider; its `id` is the registry key.
|
|
8329
|
+
* @returns the disposer that unregisters the provider.
|
|
8330
|
+
*/
|
|
8331
|
+
registerFetchProvider(provider) {
|
|
8332
|
+
return this.registerProvider(this.fetchProviders, provider);
|
|
8333
|
+
}
|
|
8334
|
+
registerProvider(store, provider) {
|
|
8335
|
+
if (store.has(provider.id)) throw new WebError(`a web provider with id "${provider.id}" is already registered`, "WEB_DUPLICATE_PROVIDER");
|
|
8336
|
+
const dispose = this.ctx.effect(function* () {
|
|
8337
|
+
store.set(provider.id, provider);
|
|
8338
|
+
yield () => store.delete(provider.id);
|
|
8339
|
+
}, "web.registerProvider()");
|
|
8340
|
+
return () => void dispose();
|
|
8341
|
+
}
|
|
8342
|
+
/**
|
|
8343
|
+
* Run one search through the selected provider. Resolves the provider at call
|
|
8344
|
+
* time with the selection rules above; throws {@link WebError} when the
|
|
8345
|
+
* capability cannot run. The seam enforces `request.maxResults` on the result:
|
|
8346
|
+
* if the provider over-returns, `sources[]` is truncated and `truncated` set.
|
|
8347
|
+
* @param request - the query and optional result limit.
|
|
8348
|
+
* @param signal - optional cancellation signal forwarded to the provider.
|
|
8349
|
+
* @returns the provider's results, capped to `request.maxResults`.
|
|
8350
|
+
*/
|
|
8351
|
+
async search(request, signal) {
|
|
8352
|
+
return capSources(await resolveProvider({
|
|
8353
|
+
providers: this.searchProviders,
|
|
8354
|
+
...this.searchProviderId !== void 0 ? { configuredId: this.searchProviderId } : {}
|
|
8355
|
+
}).search(request, signal), request.maxResults);
|
|
8356
|
+
}
|
|
8357
|
+
/**
|
|
8358
|
+
* Retrieve one URL through the selected provider. Resolves the provider at
|
|
8359
|
+
* call time with the selection rules above; throws {@link WebError} when the
|
|
8360
|
+
* capability cannot run. A non-2xx response is a result, not a throw.
|
|
8361
|
+
* @param request - the URL plus retrieval options.
|
|
8362
|
+
* @param signal - optional cancellation signal forwarded to the provider.
|
|
8363
|
+
* @returns the retrieval outcome; non-2xx responses resolve descriptively.
|
|
8364
|
+
*/
|
|
8365
|
+
async fetch(request, signal) {
|
|
8366
|
+
return resolveProvider({
|
|
8367
|
+
providers: this.fetchProviders,
|
|
8368
|
+
...this.fetchProviderId !== void 0 ? { configuredId: this.fetchProviderId } : {}
|
|
8369
|
+
}).fetch(request, signal);
|
|
8370
|
+
}
|
|
8371
|
+
};
|
|
8372
|
+
function resolveProvider(selection) {
|
|
8373
|
+
const { configuredId, providers } = selection;
|
|
8374
|
+
if (configuredId !== void 0) {
|
|
8375
|
+
const provider = providers.get(configuredId);
|
|
8376
|
+
if (!provider) throw new WebError(`configured web provider "${configuredId}" is not registered`, "WEB_PROVIDER_CONFIGURED_MISSING");
|
|
8377
|
+
if (!provider.available()) throw new WebError(`configured web provider "${configuredId}" is registered but unavailable`, "WEB_PROVIDER_CONFIGURED_UNAVAILABLE");
|
|
8378
|
+
return provider;
|
|
8379
|
+
}
|
|
8380
|
+
const usable = [...providers.values()].filter((provider) => provider.available());
|
|
8381
|
+
const [single] = usable;
|
|
8382
|
+
if (single === void 0) throw new WebError("no usable web provider is registered", "WEB_PROVIDER_UNAVAILABLE");
|
|
8383
|
+
if (usable.length > 1) throw new WebError(`multiple usable web providers are registered (${usable.map((provider) => provider.id).join(", ")}); configure one explicitly`, "WEB_PROVIDER_AMBIGUOUS");
|
|
8384
|
+
return single;
|
|
8385
|
+
}
|
|
8386
|
+
function capSources(result, maxResults) {
|
|
8387
|
+
if (maxResults === void 0 || result.sources.length <= maxResults) return result;
|
|
8388
|
+
return {
|
|
8389
|
+
...result,
|
|
8390
|
+
sources: result.sources.slice(0, maxResults),
|
|
8391
|
+
truncated: true
|
|
8392
|
+
};
|
|
8393
|
+
}
|
|
8394
|
+
|
|
8395
|
+
// src/web-search.ts
|
|
8396
|
+
var HIWORK_SEARCH_PROVIDER_ID = "hiwork-managed-search";
|
|
8397
|
+
var ME_WEB_SEARCH_PATH = "/api/me/web-search";
|
|
8398
|
+
var WEB_SEARCH_TIMEOUT_MS = 12e3;
|
|
8399
|
+
var HiworkSearchProvider = class {
|
|
8400
|
+
constructor(deps) {
|
|
8401
|
+
this.deps = deps;
|
|
8402
|
+
}
|
|
8403
|
+
id = HIWORK_SEARCH_PROVIDER_ID;
|
|
8404
|
+
available() {
|
|
8405
|
+
return true;
|
|
8406
|
+
}
|
|
8407
|
+
async search(request, signal) {
|
|
8408
|
+
if (signal?.aborted) throw aborted();
|
|
8409
|
+
let sessionCookie;
|
|
8410
|
+
try {
|
|
8411
|
+
sessionCookie = await this.deps.resolveSession();
|
|
8412
|
+
} catch (error) {
|
|
8413
|
+
this.deps.log?.(`hiwork-core: \u8054\u7F51\u641C\u7D22\u4F1A\u8BDD\u89E3\u6790\u5931\u8D25\uFF08${errorName4(error)}\uFF09`);
|
|
8414
|
+
throw new WebError("\u8054\u7F51\u641C\u7D22\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", HIWORK_SEARCH_UNREACHABLE, { cause: error });
|
|
8415
|
+
}
|
|
8416
|
+
if (sessionCookie === void 0 || sessionCookie === "") {
|
|
8417
|
+
throw new WebError("\u767B\u5F55\u540E\u624D\u80FD\u4F7F\u7528\u8054\u7F51\u641C\u7D22", HIWORK_SEARCH_UNAUTHENTICATED);
|
|
8418
|
+
}
|
|
8419
|
+
const gateway = this.deps.gateway();
|
|
8420
|
+
if (gateway === void 0) {
|
|
8421
|
+
throw new WebError("\u8054\u7F51\u641C\u7D22\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", HIWORK_SEARCH_UNREACHABLE);
|
|
8422
|
+
}
|
|
8423
|
+
const outcome = await gateway.searchWeb(
|
|
8424
|
+
sessionCookie,
|
|
8425
|
+
// maxResults 是 tool-web 传进来的上限,透传给网关少拉数据(费用按次不按条,
|
|
8426
|
+
// 但少拉条数能压响应体)。seam 仍会在结果侧强制截断,这里只是配合。
|
|
8427
|
+
{ query: request.query, ...request.maxResults !== void 0 ? { max_results: request.maxResults } : {} },
|
|
8428
|
+
signal
|
|
8429
|
+
);
|
|
8430
|
+
if (!outcome.ok) {
|
|
8431
|
+
throw outcomeToError(outcome);
|
|
8432
|
+
}
|
|
8433
|
+
const view = projectWebSearch(outcome.body);
|
|
8434
|
+
if (view === void 0) {
|
|
8435
|
+
this.deps.log?.("hiwork-core: \u7F51\u5173\u8FD4\u56DE\u7684 web-search \u54CD\u5E94\u4E0D\u7B26\u5408\u5951\u7EA6\uFF08results \u7F3A\u5931\u6216\u5F62\u72B6\u4E0D\u5BF9\uFF09");
|
|
8436
|
+
throw new WebError("\u8054\u7F51\u641C\u7D22\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u7ED3\u679C", "WEB_PROVIDER_ERROR");
|
|
8437
|
+
}
|
|
8438
|
+
return view;
|
|
8439
|
+
}
|
|
8440
|
+
};
|
|
8441
|
+
var HIWORK_SEARCH_UNAUTHENTICATED = "HIWORK_SEARCH_UNAUTHENTICATED";
|
|
8442
|
+
var HIWORK_SEARCH_DISABLED = "HIWORK_SEARCH_DISABLED";
|
|
8443
|
+
var HIWORK_SEARCH_NOT_CONFIGURED = "HIWORK_SEARCH_NOT_CONFIGURED";
|
|
8444
|
+
var HIWORK_SEARCH_LIMIT = "HIWORK_SEARCH_LIMIT";
|
|
8445
|
+
var HIWORK_SEARCH_UNREACHABLE = "HIWORK_SEARCH_UNREACHABLE";
|
|
8446
|
+
var HIWORK_SEARCH_UPSTREAM = "HIWORK_SEARCH_UPSTREAM";
|
|
8447
|
+
function aborted() {
|
|
8448
|
+
return new WebError("\u8054\u7F51\u641C\u7D22\u5DF2\u53D6\u6D88", "WEB_ABORTED");
|
|
8449
|
+
}
|
|
8450
|
+
function outcomeToError(outcome) {
|
|
8451
|
+
switch (outcome.kind) {
|
|
8452
|
+
case "aborted":
|
|
8453
|
+
return aborted();
|
|
8454
|
+
case "network":
|
|
8455
|
+
return new WebError("\u8054\u7F51\u641C\u7D22\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", HIWORK_SEARCH_UNREACHABLE);
|
|
8456
|
+
case "invalid":
|
|
8457
|
+
return new WebError("\u8054\u7F51\u641C\u7D22\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u7ED3\u679C", "WEB_PROVIDER_ERROR");
|
|
8458
|
+
case "http":
|
|
8459
|
+
return httpOutcomeToError(outcome.status, outcome.code);
|
|
8460
|
+
}
|
|
8461
|
+
}
|
|
8462
|
+
function httpOutcomeToError(status, code) {
|
|
8463
|
+
if (status === 401) return new WebError("\u767B\u5F55\u72B6\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55", HIWORK_SEARCH_UNAUTHENTICATED);
|
|
8464
|
+
if (code === "SEARCH_DISABLED") return new WebError("\u7BA1\u7406\u5458\u8FD8\u6CA1\u5F00\u542F\u8054\u7F51\u641C\u7D22", HIWORK_SEARCH_DISABLED);
|
|
8465
|
+
if (code === "SEARCH_NOT_CONFIGURED") return new WebError("\u8054\u7F51\u641C\u7D22\u8FD8\u6CA1\u6709\u914D\u7F6E\u597D\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458", HIWORK_SEARCH_NOT_CONFIGURED);
|
|
8466
|
+
if (status === 429 || code === "SEARCH_LIMIT_EXCEEDED") return new WebError("\u4ECA\u5929\u7684\u8054\u7F51\u641C\u7D22\u6B21\u6570\u5DF2\u7528\u5B8C\uFF0C\u660E\u5929\u518D\u6765", HIWORK_SEARCH_LIMIT);
|
|
8467
|
+
if (status === 502 || code === "SEARCH_UPSTREAM_ERROR") return new WebError("\u641C\u7D22\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", HIWORK_SEARCH_UPSTREAM);
|
|
8468
|
+
return new WebError("\u8054\u7F51\u641C\u7D22\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", "WEB_PROVIDER_ERROR");
|
|
8469
|
+
}
|
|
8470
|
+
function textOrUndefined8(value) {
|
|
8471
|
+
if (typeof value !== "string") return void 0;
|
|
8472
|
+
const text = value.trim();
|
|
8473
|
+
return text === "" ? void 0 : text;
|
|
8474
|
+
}
|
|
8475
|
+
function projectWebSearch(body) {
|
|
8476
|
+
const raw = body["results"];
|
|
8477
|
+
if (!Array.isArray(raw)) return void 0;
|
|
8478
|
+
const sources = [];
|
|
8479
|
+
for (const item of raw) {
|
|
8480
|
+
if (item === null || typeof item !== "object") continue;
|
|
8481
|
+
const record = item;
|
|
8482
|
+
const url = textOrUndefined8(record["url"]);
|
|
8483
|
+
if (url === void 0) continue;
|
|
8484
|
+
const title = textOrUndefined8(record["title"]);
|
|
8485
|
+
const snippet = textOrUndefined8(record["snippet"]) ?? textOrUndefined8(record["content"]);
|
|
8486
|
+
const publishedAt = textOrUndefined8(record["published_at"]);
|
|
8487
|
+
sources.push({
|
|
8488
|
+
url,
|
|
8489
|
+
...title !== void 0 ? { title } : {},
|
|
8490
|
+
...snippet !== void 0 ? { snippet } : {},
|
|
8491
|
+
...publishedAt !== void 0 ? { publishedAt } : {}
|
|
8492
|
+
});
|
|
8493
|
+
}
|
|
8494
|
+
return { sources, truncated: false };
|
|
8495
|
+
}
|
|
8496
|
+
function errorName4(error) {
|
|
8497
|
+
return error instanceof Error ? error.name : typeof error;
|
|
8498
|
+
}
|
|
8499
|
+
function createWebSearchGateway(baseURL, opts = {}) {
|
|
8500
|
+
const root = baseURL.replace(/\/+$/, "");
|
|
8501
|
+
const timeoutMs = opts.timeoutMs ?? WEB_SEARCH_TIMEOUT_MS;
|
|
8502
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
8503
|
+
return {
|
|
8504
|
+
async searchWeb(sessionCookie, body, signal) {
|
|
8505
|
+
const signals = [AbortSignal.timeout(timeoutMs)];
|
|
8506
|
+
if (signal !== void 0) signals.push(signal);
|
|
8507
|
+
const merged = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
|
|
8508
|
+
let res;
|
|
8509
|
+
try {
|
|
8510
|
+
res = await doFetch(`${root}${ME_WEB_SEARCH_PATH}`, {
|
|
8511
|
+
method: "POST",
|
|
8512
|
+
headers: {
|
|
8513
|
+
"user-agent": `hiwork-core/${PKG_VERSION}`,
|
|
8514
|
+
cookie: sessionCookie,
|
|
8515
|
+
"content-type": "application/json"
|
|
8516
|
+
},
|
|
8517
|
+
body: JSON.stringify(body),
|
|
8518
|
+
signal: merged
|
|
8519
|
+
});
|
|
8520
|
+
} catch (error) {
|
|
8521
|
+
if (signal?.aborted) return { ok: false, kind: "aborted" };
|
|
8522
|
+
return { ok: false, kind: "network" };
|
|
8523
|
+
}
|
|
8524
|
+
if (!res.ok) {
|
|
8525
|
+
let code;
|
|
8526
|
+
try {
|
|
8527
|
+
const parsed2 = await res.json();
|
|
8528
|
+
if (typeof parsed2?.code === "string" && parsed2.code !== "") code = parsed2.code;
|
|
8529
|
+
} catch {
|
|
8530
|
+
}
|
|
8531
|
+
return { ok: false, kind: "http", status: res.status, ...code !== void 0 ? { code } : {} };
|
|
8532
|
+
}
|
|
8533
|
+
let parsed;
|
|
8534
|
+
try {
|
|
8535
|
+
parsed = await res.json();
|
|
8536
|
+
} catch {
|
|
8537
|
+
return { ok: false, kind: "invalid" };
|
|
8538
|
+
}
|
|
8539
|
+
if (parsed === null || typeof parsed !== "object") return { ok: false, kind: "invalid" };
|
|
8540
|
+
return { ok: true, body: parsed };
|
|
8541
|
+
}
|
|
8542
|
+
};
|
|
8543
|
+
}
|
|
8544
|
+
function registerManagedSearchProvider(web, deps) {
|
|
8545
|
+
return web.registerSearchProvider(new HiworkSearchProvider(deps));
|
|
8546
|
+
}
|
|
8547
|
+
|
|
8548
|
+
// src/index.ts
|
|
8549
|
+
var name = "hiwork-core";
|
|
8550
|
+
var inject = ["settings", "credentials", "workspaceRegistry", "connection", "web"];
|
|
8551
|
+
var NS = "ai-router";
|
|
8552
|
+
var PI_AI_NS = "llm-pi-ai";
|
|
8553
|
+
var lastErrorSchema = Schema.object({ code: Schema.string().required(), message: Schema.string().required() }).default(void 0);
|
|
8554
|
+
var Config = Schema.object({
|
|
8555
|
+
baseURL: Schema.string(),
|
|
8556
|
+
keyId: Schema.string(),
|
|
8557
|
+
username: Schema.string(),
|
|
8558
|
+
displayName: Schema.string(),
|
|
8559
|
+
lastLogin: Schema.object({ at: Schema.string().required(), modelCount: Schema.number().required(), gatewayName: Schema.string().required() }).default(void 0),
|
|
8560
|
+
lastError: lastErrorSchema,
|
|
8561
|
+
pendingLogin: Schema.object({ username: Schema.string().required(), passwordRef: Schema.string().required() }).default(void 0),
|
|
8562
|
+
rememberPassword: Schema.boolean().default(false),
|
|
8563
|
+
refreshRequest: Schema.object({ at: Schema.string().required() }).default(void 0),
|
|
8564
|
+
logoutRequest: Schema.object({ at: Schema.string().required() }).default(void 0),
|
|
8565
|
+
browserLoginRequest: Schema.object({ at: Schema.string().required() }).default(void 0),
|
|
8566
|
+
browserLogin: Schema.object({ authorizeUrl: Schema.string().required(), startedAt: Schema.string().required() }).default(void 0),
|
|
8567
|
+
// 三值枚举:非法值写入直接被 schema 拒绝(客户端还会再归一一次,双保险)。
|
|
8568
|
+
loginMode: Schema.union([Schema.const("browser"), Schema.const("form"), Schema.const("both")]),
|
|
8569
|
+
passwordLogin: Schema.boolean(),
|
|
8570
|
+
budgets: Schema.array(Schema.object({
|
|
8571
|
+
model_name: Schema.string().required(),
|
|
8572
|
+
total_budget: Schema.number(),
|
|
6824
8573
|
consumed_budget: Schema.number(),
|
|
6825
8574
|
remaining_budget: Schema.number()
|
|
6826
8575
|
})).default(void 0),
|
|
@@ -6921,14 +8670,14 @@ function parseDeviceInfo(message) {
|
|
|
6921
8670
|
const id = deviceId.value?.trim();
|
|
6922
8671
|
if (id === void 0 || id === "") return void 0;
|
|
6923
8672
|
const name2 = deviceName.value?.trim();
|
|
6924
|
-
const
|
|
8673
|
+
const version2 = appVersion.value?.trim();
|
|
6925
8674
|
return {
|
|
6926
8675
|
deviceId: id,
|
|
6927
8676
|
...name2 === void 0 || name2 === "" ? {} : { deviceName: name2 },
|
|
6928
|
-
...
|
|
8677
|
+
...version2 === void 0 || version2 === "" ? {} : { appVersion: version2 }
|
|
6929
8678
|
};
|
|
6930
8679
|
}
|
|
6931
|
-
function
|
|
8680
|
+
function errorName5(error) {
|
|
6932
8681
|
return error instanceof Error ? error.name : typeof error;
|
|
6933
8682
|
}
|
|
6934
8683
|
function registerIpcMessageHandler(ports) {
|
|
@@ -6955,12 +8704,12 @@ function registerIpcMessageHandler(ports) {
|
|
|
6955
8704
|
authInFlight = true;
|
|
6956
8705
|
try {
|
|
6957
8706
|
void Promise.resolve(ports.complete(input)).catch((error) => {
|
|
6958
|
-
log(`hiwork-core: \u6D4F\u89C8\u5668\u6388\u6743\u56DE\u8C03\u5904\u7406\u5F02\u5E38\uFF08${
|
|
8707
|
+
log(`hiwork-core: \u6D4F\u89C8\u5668\u6388\u6743\u56DE\u8C03\u5904\u7406\u5F02\u5E38\uFF08${errorName5(error)}\uFF09`);
|
|
6959
8708
|
}).finally(() => {
|
|
6960
8709
|
authInFlight = false;
|
|
6961
8710
|
});
|
|
6962
8711
|
} catch (error) {
|
|
6963
|
-
log(`hiwork-core: \u6D4F\u89C8\u5668\u6388\u6743\u56DE\u8C03\u5206\u53D1\u5931\u8D25\uFF08${
|
|
8712
|
+
log(`hiwork-core: \u6D4F\u89C8\u5668\u6388\u6743\u56DE\u8C03\u5206\u53D1\u5931\u8D25\uFF08${errorName5(error)}\uFF09`);
|
|
6964
8713
|
authInFlight = false;
|
|
6965
8714
|
}
|
|
6966
8715
|
return;
|
|
@@ -7008,12 +8757,12 @@ async function projectLoginMode(opts) {
|
|
|
7008
8757
|
}
|
|
7009
8758
|
}
|
|
7010
8759
|
} catch (error) {
|
|
7011
|
-
opts.log?.(`hiwork-core: \u5BA2\u6237\u7AEF\u7B56\u7565\u62C9\u53D6\u5931\u8D25\uFF0C\u767B\u5F55\u65B9\u5F0F\u56DE\u9000 both\uFF08${
|
|
8760
|
+
opts.log?.(`hiwork-core: \u5BA2\u6237\u7AEF\u7B56\u7565\u62C9\u53D6\u5931\u8D25\uFF0C\u767B\u5F55\u65B9\u5F0F\u56DE\u9000 both\uFF08${errorName5(error)}\uFF09`);
|
|
7012
8761
|
}
|
|
7013
8762
|
try {
|
|
7014
8763
|
await opts.state.patch({ set: { loginMode, passwordLogin } });
|
|
7015
8764
|
} catch (error) {
|
|
7016
|
-
opts.log?.(`hiwork-core: \u5BA2\u6237\u7AEF\u7B56\u7565\u5199\u5165\u5931\u8D25\uFF08${
|
|
8765
|
+
opts.log?.(`hiwork-core: \u5BA2\u6237\u7AEF\u7B56\u7565\u5199\u5165\u5931\u8D25\uFF08${errorName5(error)}\uFF09`);
|
|
7017
8766
|
}
|
|
7018
8767
|
return loginMode;
|
|
7019
8768
|
}
|
|
@@ -7151,6 +8900,16 @@ function apply(ctx, config) {
|
|
|
7151
8900
|
ctx.logger.warn(message);
|
|
7152
8901
|
}
|
|
7153
8902
|
}), "hiwork-core: daily rpc");
|
|
8903
|
+
ctx.effect(() => registerVoiceRpc({ connection, logger: ctx.logger }, {
|
|
8904
|
+
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
8905
|
+
gateway: () => {
|
|
8906
|
+
const baseURL = current().baseURL;
|
|
8907
|
+
return baseURL === void 0 || baseURL === "" ? void 0 : gatewayFor(baseURL);
|
|
8908
|
+
},
|
|
8909
|
+
log: (message) => {
|
|
8910
|
+
ctx.logger.warn(message);
|
|
8911
|
+
}
|
|
8912
|
+
}), "hiwork-core: voice rpc");
|
|
7154
8913
|
const managedMcpDeps = {
|
|
7155
8914
|
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
7156
8915
|
gateway: () => {
|
|
@@ -7283,6 +9042,16 @@ function apply(ctx, config) {
|
|
|
7283
9042
|
ctx.logger.warn(message);
|
|
7284
9043
|
}
|
|
7285
9044
|
}), "hiwork-core: memory config service");
|
|
9045
|
+
ctx.effect(() => provideKnowledgeConfig(ctx, {
|
|
9046
|
+
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
9047
|
+
gateway: () => {
|
|
9048
|
+
const baseURL = current().baseURL;
|
|
9049
|
+
return baseURL === void 0 || baseURL === "" ? void 0 : createKnowledgeConfigGateway(baseURL);
|
|
9050
|
+
},
|
|
9051
|
+
log: (message) => {
|
|
9052
|
+
ctx.logger.warn(message);
|
|
9053
|
+
}
|
|
9054
|
+
}), "hiwork-core: knowledge config service");
|
|
7286
9055
|
ctx.effect(() => provideOfficeRelay(ctx, {
|
|
7287
9056
|
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
7288
9057
|
gateway: () => {
|
|
@@ -7293,6 +9062,19 @@ function apply(ctx, config) {
|
|
|
7293
9062
|
ctx.logger.warn(message);
|
|
7294
9063
|
}
|
|
7295
9064
|
}), "hiwork-core: office relay");
|
|
9065
|
+
const web = ctx.get("web");
|
|
9066
|
+
if (web !== void 0) {
|
|
9067
|
+
registerManagedSearchProvider(web, {
|
|
9068
|
+
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
9069
|
+
gateway: () => {
|
|
9070
|
+
const baseURL = current().baseURL;
|
|
9071
|
+
return baseURL === void 0 || baseURL === "" ? void 0 : createWebSearchGateway(baseURL);
|
|
9072
|
+
},
|
|
9073
|
+
log: (message) => {
|
|
9074
|
+
ctx.logger.warn(message);
|
|
9075
|
+
}
|
|
9076
|
+
});
|
|
9077
|
+
}
|
|
7296
9078
|
ctx.effect(() => registerAppVersionRpc({ connection, logger: ctx.logger }, {
|
|
7297
9079
|
appVersion: () => pushedAppVersion(),
|
|
7298
9080
|
log: (message) => {
|