hiwork-core 0.0.37 → 0.0.39
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/lib/ai-router-client.js +152 -4
- package/lib/browser-login.js +9 -2
- package/lib/client-policy.js +77 -2
- package/lib/client.js +34 -114
- package/lib/identity-context.js +50 -0
- package/lib/index.js +532 -79
- package/lib/knowledge-config.js +14 -12
- package/lib/memory-config.js +7 -7
- package/lib/orchestration.js +50 -3
- package/lib/provision-session.js +1 -0
- package/lib/provision.js +5 -0
- package/lib/session-fanout.js +29 -0
- package/lib/session-supervisor.js +156 -0
- package/lib/ttl-cache.js +45 -0
- package/lib/types/ai-router-client.d.ts +74 -0
- package/lib/types/client/menu-preferences.d.ts +4 -3
- package/lib/types/client/styles.d.ts +5 -4
- package/lib/types/client/types.d.ts +7 -1
- package/lib/types/client/user-badge.d.ts +7 -2
- package/lib/types/client-policy.d.ts +30 -2
- package/lib/types/identity-context.d.ts +54 -0
- package/lib/types/index.d.ts +15 -3
- package/lib/types/orchestration.d.ts +5 -3
- package/lib/types/provision-session.d.ts +9 -0
- package/lib/types/provision.d.ts +5 -0
- package/lib/types/session-fanout.d.ts +19 -0
- package/lib/types/session-supervisor.d.ts +101 -0
- package/lib/types/ttl-cache.d.ts +29 -0
- package/lib/types/types.d.ts +6 -0
- package/package.json +26 -25
package/lib/index.js
CHANGED
|
@@ -8267,7 +8267,7 @@ defineMethod("transform", [
|
|
|
8267
8267
|
], ({ inner }, isInner) => inner.toString(isInner));
|
|
8268
8268
|
|
|
8269
8269
|
// src/version.ts
|
|
8270
|
-
var PKG_VERSION = false ? "dev" : "0.0.
|
|
8270
|
+
var PKG_VERSION = false ? "dev" : "0.0.39";
|
|
8271
8271
|
|
|
8272
8272
|
// src/browser-login.ts
|
|
8273
8273
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
@@ -8278,6 +8278,7 @@ var API_KEY_REF = "AI_ROUTER_API_KEY";
|
|
|
8278
8278
|
var SESSION_REF = "AI_ROUTER_SESSION";
|
|
8279
8279
|
var PENDING_PASSWORD_REF = "AI_ROUTER_PENDING_PASSWORD";
|
|
8280
8280
|
var REMEMBERED_PASSWORD_REF = "AI_ROUTER_REMEMBERED_PASSWORD";
|
|
8281
|
+
var REFRESH_TOKEN_REF = "AI_ROUTER_REFRESH_TOKEN";
|
|
8281
8282
|
var PROVIDER_ROUTES = {
|
|
8282
8283
|
"ai-router-chat": "openai-completions",
|
|
8283
8284
|
"ai-router-anthropic": "anthropic-messages",
|
|
@@ -8435,6 +8436,7 @@ async function provisionSession(opts) {
|
|
|
8435
8436
|
const displayName = opts.user.display_name?.trim() || void 0;
|
|
8436
8437
|
const set2 = {
|
|
8437
8438
|
...opts.username === void 0 ? {} : { username: opts.username },
|
|
8439
|
+
...opts.sessionExpiresAt === void 0 ? {} : { sessionExpiresAt: opts.sessionExpiresAt },
|
|
8438
8440
|
...displayName === void 0 ? {} : { displayName },
|
|
8439
8441
|
lastLogin: {
|
|
8440
8442
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -8600,12 +8602,15 @@ async function completeBrowserLogin(input, opts) {
|
|
|
8600
8602
|
}
|
|
8601
8603
|
const baseURL = opts.value.baseURL;
|
|
8602
8604
|
if (baseURL === void 0 || baseURL === "") return await failBrowserLogin(opts.state, NO_BASE_URL_ERROR, log);
|
|
8603
|
-
const { sessionCookie, user } = await opts.gateway.exchangeCode({
|
|
8605
|
+
const { sessionCookie, user, sessionExpiresAt, refreshToken } = await opts.gateway.exchangeCode({
|
|
8604
8606
|
code: input.code,
|
|
8605
8607
|
codeVerifier: pending.codeVerifier,
|
|
8606
8608
|
deviceId: pending.deviceId
|
|
8607
8609
|
});
|
|
8608
8610
|
await opts.credentials.set(SESSION_REF, sessionCookie);
|
|
8611
|
+
if (refreshToken === void 0) await opts.credentials.unset(REFRESH_TOKEN_REF).catch(() => {
|
|
8612
|
+
});
|
|
8613
|
+
else await opts.credentials.set(REFRESH_TOKEN_REF, refreshToken);
|
|
8609
8614
|
const username = typeof user.username === "string" && user.username.trim() !== "" ? user.username.trim() : void 0;
|
|
8610
8615
|
await provisionSession({
|
|
8611
8616
|
gateway: opts.gateway,
|
|
@@ -8617,6 +8622,7 @@ async function completeBrowserLogin(input, opts) {
|
|
|
8617
8622
|
sessionCookie,
|
|
8618
8623
|
user,
|
|
8619
8624
|
username,
|
|
8625
|
+
sessionExpiresAt,
|
|
8620
8626
|
requestUnset: ["browserLoginRequest", "browserLogin"],
|
|
8621
8627
|
...opts.defaultModel === void 0 ? {} : { defaultModel: opts.defaultModel },
|
|
8622
8628
|
...opts.ensureWorkspace === void 0 ? {} : { ensureWorkspace: opts.ensureWorkspace }
|
|
@@ -8647,6 +8653,13 @@ function gatewayUserAgent(version2 = desktopAppVersion()) {
|
|
|
8647
8653
|
}
|
|
8648
8654
|
|
|
8649
8655
|
// src/ai-router-client.ts
|
|
8656
|
+
var sessionActivitySink;
|
|
8657
|
+
function setSessionActivitySink(sink) {
|
|
8658
|
+
sessionActivitySink = sink;
|
|
8659
|
+
}
|
|
8660
|
+
function clearSessionActivitySink(sink) {
|
|
8661
|
+
if (sessionActivitySink === sink) sessionActivitySink = void 0;
|
|
8662
|
+
}
|
|
8650
8663
|
async function knowledgeErrorCodeFromBody(res) {
|
|
8651
8664
|
try {
|
|
8652
8665
|
const payload = await res.clone().json();
|
|
@@ -8658,6 +8671,7 @@ async function knowledgeErrorCodeFromBody(res) {
|
|
|
8658
8671
|
var AUTH_AUTHORIZE_PATH = "/api/auth/authorize";
|
|
8659
8672
|
var AUTH_TOKEN_PATH = "/api/auth/token";
|
|
8660
8673
|
var AUTH_SESSIONS_PATH = "/api/auth/sessions";
|
|
8674
|
+
var AUTH_REFRESH_PATH = "/api/auth/refresh";
|
|
8661
8675
|
var ME_ANALYTICS_SUMMARY_PATH = "/api/me/analytics/summary";
|
|
8662
8676
|
var ME_ANALYTICS_TRENDS_PATH = "/api/me/analytics/trends";
|
|
8663
8677
|
var ME_ANALYTICS_MODEL_TRENDS_PATH = "/api/me/analytics/model-trends";
|
|
@@ -8758,8 +8772,16 @@ var AiRouterClient = class {
|
|
|
8758
8772
|
if (res.status === 401) throw new GatewayError("AUTH_FAILED", "\u7528\u6237\u540D\u6216\u5BC6\u7801\u9519\u8BEF", 401);
|
|
8759
8773
|
if (!res.ok) throw new GatewayError("GATEWAY_UNREACHABLE", `\u7F51\u5173\u8FD4\u56DE\u9519\u8BEF\uFF08HTTP ${res.status}\uFF09`, res.status);
|
|
8760
8774
|
if (sid === void 0) throw new GatewayError("GATEWAY_UNREACHABLE", "\u7F51\u5173\u767B\u5F55\u6210\u529F\u4F46\u672A\u8FD4\u56DE\u4F1A\u8BDD Cookie", res.status);
|
|
8761
|
-
const user = await res.json();
|
|
8762
|
-
|
|
8775
|
+
const { expires_at: rawExpiresAt, refresh_token: rawRefreshToken, ...user } = await res.json();
|
|
8776
|
+
const bodyExpiresAt = typeof rawExpiresAt === "string" && !Number.isNaN(Date.parse(rawExpiresAt)) ? rawExpiresAt : void 0;
|
|
8777
|
+
const sessionExpiresAt = bodyExpiresAt ?? parseSessionCookieExpiry(res.headers);
|
|
8778
|
+
const refreshToken = typeof rawRefreshToken === "string" && rawRefreshToken !== "" ? rawRefreshToken : void 0;
|
|
8779
|
+
return {
|
|
8780
|
+
sessionCookie: `session_id=${sid}`,
|
|
8781
|
+
user,
|
|
8782
|
+
...sessionExpiresAt === void 0 ? {} : { sessionExpiresAt },
|
|
8783
|
+
...refreshToken === void 0 ? {} : { refreshToken }
|
|
8784
|
+
};
|
|
8763
8785
|
}
|
|
8764
8786
|
/**
|
|
8765
8787
|
* POST /api/auth/token:用一次性 code + PKCE verifier 换取会话。
|
|
@@ -8781,7 +8803,49 @@ var AiRouterClient = class {
|
|
|
8781
8803
|
if (data === void 0 || data.session_id === void 0 || data.session_id === "") {
|
|
8782
8804
|
throw new GatewayError("GATEWAY_UNREACHABLE", "\u7F51\u5173\u5151\u6362\u6210\u529F\u4F46\u672A\u8FD4\u56DE\u4F1A\u8BDD\u6807\u8BC6", res.status);
|
|
8783
8805
|
}
|
|
8784
|
-
|
|
8806
|
+
const rawExpiresAt = typeof data.expires_at === "string" ? data.expires_at : void 0;
|
|
8807
|
+
const sessionExpiresAt = rawExpiresAt !== void 0 && !Number.isNaN(Date.parse(rawExpiresAt)) ? rawExpiresAt : void 0;
|
|
8808
|
+
const refreshToken = typeof data.refresh_token === "string" && data.refresh_token !== "" ? data.refresh_token : void 0;
|
|
8809
|
+
return {
|
|
8810
|
+
sessionCookie: `session_id=${data.session_id}`,
|
|
8811
|
+
user: data.user,
|
|
8812
|
+
...sessionExpiresAt === void 0 ? {} : { sessionExpiresAt },
|
|
8813
|
+
...refreshToken === void 0 ? {} : { refreshToken }
|
|
8814
|
+
};
|
|
8815
|
+
}
|
|
8816
|
+
/**
|
|
8817
|
+
* POST /api/auth/refresh:用 refresh grant 换一份新会话(M2 网关的静默重认证)。
|
|
8818
|
+
*
|
|
8819
|
+
* 拒绝语义必须分开,调用方据此决定「弃用 grant」还是「保留待重试」:
|
|
8820
|
+
* - 400 = grant 无效(过期 / 已被轮换 / 复用检测拒绝)→ `REFRESH_GRANT_INVALID`,本地作废;
|
|
8821
|
+
* - 404 = 老网关根本没有这条路由 → `REFRESH_GRANT_ABSENT`,本地作废且**静默降级**;
|
|
8822
|
+
* - 其余非 2xx(5xx / 反代错误页)与网络层异常 → `GATEWAY_UNREACHABLE`,grant 保留,
|
|
8823
|
+
* 下次 SESSION_EXPIRED 再试。
|
|
8824
|
+
*
|
|
8825
|
+
* 任何日志/异常信息都不得包含 refresh_token / session_id 明文。
|
|
8826
|
+
*/
|
|
8827
|
+
async refreshSession(refreshToken) {
|
|
8828
|
+
const res = await this.requestOrUnreachable(AUTH_REFRESH_PATH, {
|
|
8829
|
+
method: "POST",
|
|
8830
|
+
body: { refresh_token: refreshToken }
|
|
8831
|
+
});
|
|
8832
|
+
if (res.status === 400) throw new GatewayError("REFRESH_GRANT_INVALID", "\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55", 400);
|
|
8833
|
+
if (res.status === 404) throw new GatewayError("REFRESH_GRANT_ABSENT", "\u7F51\u5173\u4E0D\u652F\u6301\u9759\u9ED8\u7EED\u671F", 404);
|
|
8834
|
+
if (!res.ok) throw new GatewayError("GATEWAY_UNREACHABLE", `\u7F51\u5173\u8FD4\u56DE\u9519\u8BEF\uFF08HTTP ${res.status}\uFF09`, res.status);
|
|
8835
|
+
const data = await readJson(res);
|
|
8836
|
+
const sid = typeof data?.session_id === "string" && data.session_id !== "" ? data.session_id : extractSessionId(res.headers);
|
|
8837
|
+
if (data === void 0 || data.user === void 0 || sid === void 0) {
|
|
8838
|
+
throw new GatewayError("GATEWAY_UNREACHABLE", "\u7F51\u5173\u7EED\u671F\u6210\u529F\u4F46\u672A\u8FD4\u56DE\u4F1A\u8BDD\u6807\u8BC6", res.status);
|
|
8839
|
+
}
|
|
8840
|
+
const rawExpiresAt = typeof data.expires_at === "string" ? data.expires_at : void 0;
|
|
8841
|
+
const sessionExpiresAt = rawExpiresAt !== void 0 && !Number.isNaN(Date.parse(rawExpiresAt)) ? rawExpiresAt : void 0;
|
|
8842
|
+
const rotated = typeof data.refresh_token === "string" && data.refresh_token !== "" ? data.refresh_token : void 0;
|
|
8843
|
+
return {
|
|
8844
|
+
sessionCookie: `session_id=${sid}`,
|
|
8845
|
+
user: data.user,
|
|
8846
|
+
...sessionExpiresAt === void 0 ? {} : { sessionExpiresAt },
|
|
8847
|
+
...rotated === void 0 ? {} : { refreshToken: rotated }
|
|
8848
|
+
};
|
|
8785
8849
|
}
|
|
8786
8850
|
/** GET /api/auth/sessions:当前账号的登录设备列表。 */
|
|
8787
8851
|
async listSessions(sessionCookie) {
|
|
@@ -9016,6 +9080,9 @@ var AiRouterClient = class {
|
|
|
9016
9080
|
if (res.status === 503) {
|
|
9017
9081
|
throw new GatewayError("MCP_ASSERTION_DISABLED", "\u672C\u90E8\u7F72\u672A\u542F\u7528 MCP \u65AD\u8A00\u7B7E\u53D1\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458", 503);
|
|
9018
9082
|
}
|
|
9083
|
+
if (res.status === 429) {
|
|
9084
|
+
throw new GatewayError("MCP_ASSERTION_RATE_LIMITED", "\u65AD\u8A00\u7B7E\u53D1\u8FC7\u4E8E\u9891\u7E41\uFF0C\u7A0D\u540E\u81EA\u52A8\u91CD\u8BD5", 429);
|
|
9085
|
+
}
|
|
9019
9086
|
if (!res.ok) throw new GatewayError("GATEWAY_UNREACHABLE", `\u7F51\u5173\u8FD4\u56DE\u9519\u8BEF\uFF08HTTP ${res.status}\uFF09`, res.status);
|
|
9020
9087
|
return await parseMeJson(res);
|
|
9021
9088
|
}
|
|
@@ -9389,7 +9456,19 @@ var AiRouterClient = class {
|
|
|
9389
9456
|
opts.rawBody.byteOffset + opts.rawBody.byteLength
|
|
9390
9457
|
);
|
|
9391
9458
|
} else if (opts.body !== void 0) init.body = JSON.stringify(opts.body);
|
|
9392
|
-
|
|
9459
|
+
const res = await fetch(`${this.baseURL}${path}`, init);
|
|
9460
|
+
if (opts.sessionCookie !== void 0) {
|
|
9461
|
+
try {
|
|
9462
|
+
if (res.status === 401) sessionActivitySink?.({ kind: "unauthorized" });
|
|
9463
|
+
else if (res.ok) {
|
|
9464
|
+
const headerExpiresAt = res.headers.get("x-session-expires-at");
|
|
9465
|
+
const expiresAt = headerExpiresAt !== null && !Number.isNaN(Date.parse(headerExpiresAt)) ? headerExpiresAt : void 0;
|
|
9466
|
+
sessionActivitySink?.(expiresAt === void 0 ? { kind: "success" } : { kind: "success", expiresAt });
|
|
9467
|
+
}
|
|
9468
|
+
} catch {
|
|
9469
|
+
}
|
|
9470
|
+
}
|
|
9471
|
+
return res;
|
|
9393
9472
|
}
|
|
9394
9473
|
};
|
|
9395
9474
|
function headerSafeValue(value) {
|
|
@@ -9427,6 +9506,27 @@ function extractSessionId(headers) {
|
|
|
9427
9506
|
}
|
|
9428
9507
|
return void 0;
|
|
9429
9508
|
}
|
|
9509
|
+
function parseSessionCookieExpiry(headers, now = Date.now()) {
|
|
9510
|
+
const raws = typeof headers.getSetCookie === "function" ? headers.getSetCookie() : [headers.get("set-cookie")].filter((raw) => raw !== null);
|
|
9511
|
+
for (const raw of raws) {
|
|
9512
|
+
for (const section of raw.split(/,\s*(?=[!#$%&'*+\-.^_`|~0-9A-Za-z]+=)/)) {
|
|
9513
|
+
if (!/(?:^|;\s*)session_id=/.test(section)) continue;
|
|
9514
|
+
const expires = /;\s*Expires=([^;]+)/i.exec(section);
|
|
9515
|
+
const expiresRaw = expires?.[1];
|
|
9516
|
+
if (expiresRaw !== void 0) {
|
|
9517
|
+
const ms = Date.parse(expiresRaw);
|
|
9518
|
+
if (!Number.isNaN(ms)) return new Date(ms).toISOString();
|
|
9519
|
+
}
|
|
9520
|
+
const maxAge = /;\s*Max-Age=(-?\d+)/i.exec(section);
|
|
9521
|
+
if (maxAge !== null) {
|
|
9522
|
+
const seconds = Number(maxAge[1]);
|
|
9523
|
+
if (Number.isFinite(seconds)) return new Date(now + seconds * 1e3).toISOString();
|
|
9524
|
+
}
|
|
9525
|
+
return void 0;
|
|
9526
|
+
}
|
|
9527
|
+
}
|
|
9528
|
+
return void 0;
|
|
9529
|
+
}
|
|
9430
9530
|
async function readJson(res) {
|
|
9431
9531
|
try {
|
|
9432
9532
|
return await res.json();
|
|
@@ -9577,6 +9677,58 @@ async function fetchClientPolicy(opts) {
|
|
|
9577
9677
|
return void 0;
|
|
9578
9678
|
}
|
|
9579
9679
|
}
|
|
9680
|
+
var CLIENT_POLICY_POLL_INTERVAL_MS = 6 * 60 * 6e4;
|
|
9681
|
+
var CLIENT_POLICY_RETRY_DELAYS_MS = [6e4, 10 * 6e4, 60 * 6e4];
|
|
9682
|
+
function createClientPolicyPoller(deps) {
|
|
9683
|
+
let timer;
|
|
9684
|
+
let disposed = false;
|
|
9685
|
+
let running = false;
|
|
9686
|
+
let retryIndex = 0;
|
|
9687
|
+
const schedule = (delayMs) => {
|
|
9688
|
+
if (disposed) return;
|
|
9689
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
9690
|
+
timer = setTimeout(() => {
|
|
9691
|
+
timer = void 0;
|
|
9692
|
+
void run();
|
|
9693
|
+
}, delayMs);
|
|
9694
|
+
timer.unref?.();
|
|
9695
|
+
};
|
|
9696
|
+
const run = async () => {
|
|
9697
|
+
if (disposed || running) return;
|
|
9698
|
+
running = true;
|
|
9699
|
+
let ok = false;
|
|
9700
|
+
try {
|
|
9701
|
+
ok = await deps.attempt();
|
|
9702
|
+
} catch {
|
|
9703
|
+
ok = false;
|
|
9704
|
+
} finally {
|
|
9705
|
+
running = false;
|
|
9706
|
+
}
|
|
9707
|
+
if (disposed) return;
|
|
9708
|
+
if (ok) {
|
|
9709
|
+
retryIndex = 0;
|
|
9710
|
+
schedule(CLIENT_POLICY_POLL_INTERVAL_MS);
|
|
9711
|
+
return;
|
|
9712
|
+
}
|
|
9713
|
+
const delay2 = CLIENT_POLICY_RETRY_DELAYS_MS[Math.min(retryIndex, CLIENT_POLICY_RETRY_DELAYS_MS.length - 1)];
|
|
9714
|
+
retryIndex += 1;
|
|
9715
|
+
deps.log?.(`hiwork-core: \u5BA2\u6237\u7AEF\u7B56\u7565\u62C9\u53D6\u5931\u8D25\uFF0C${Math.round(delay2 / 1e3)}s \u540E\u91CD\u8BD5`);
|
|
9716
|
+
schedule(delay2);
|
|
9717
|
+
};
|
|
9718
|
+
return {
|
|
9719
|
+
trigger: () => {
|
|
9720
|
+
if (disposed || running || timer !== void 0) return;
|
|
9721
|
+
void run();
|
|
9722
|
+
},
|
|
9723
|
+
dispose: () => {
|
|
9724
|
+
disposed = true;
|
|
9725
|
+
if (timer !== void 0) {
|
|
9726
|
+
clearTimeout(timer);
|
|
9727
|
+
timer = void 0;
|
|
9728
|
+
}
|
|
9729
|
+
}
|
|
9730
|
+
};
|
|
9731
|
+
}
|
|
9580
9732
|
|
|
9581
9733
|
// src/default-model.ts
|
|
9582
9734
|
var DEFAULT_MODEL_NS = "agent-default-model";
|
|
@@ -9783,14 +9935,18 @@ async function runLogin(opts) {
|
|
|
9783
9935
|
const password = await opts.credentials.resolve(pending.passwordRef);
|
|
9784
9936
|
if (password === void 0) throw new GatewayError("AUTH_FAILED", "\u767B\u5F55\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
|
|
9785
9937
|
const device = await resolveDeviceInfo(opts.credentials);
|
|
9786
|
-
const { sessionCookie, user } = await opts.gateway.login(pending.username, password.value, device);
|
|
9938
|
+
const { sessionCookie, user, sessionExpiresAt, refreshToken } = await opts.gateway.login(pending.username, password.value, device);
|
|
9787
9939
|
await opts.credentials.set(SESSION_REF, sessionCookie);
|
|
9940
|
+
if (refreshToken === void 0) await opts.credentials.unset(REFRESH_TOKEN_REF).catch(() => {
|
|
9941
|
+
});
|
|
9942
|
+
else await opts.credentials.set(REFRESH_TOKEN_REF, refreshToken);
|
|
9788
9943
|
await provisionSession({
|
|
9789
9944
|
...opts,
|
|
9790
9945
|
baseURL,
|
|
9791
9946
|
sessionCookie,
|
|
9792
9947
|
user,
|
|
9793
9948
|
username: pending.username,
|
|
9949
|
+
sessionExpiresAt,
|
|
9794
9950
|
requestUnset: ["pendingLogin"],
|
|
9795
9951
|
onApiKeyWritten: async () => {
|
|
9796
9952
|
if (opts.value.rememberPassword === true) await opts.credentials.set(REMEMBERED_PASSWORD_REF, password.value);
|
|
@@ -9814,6 +9970,9 @@ async function runLogin(opts) {
|
|
|
9814
9970
|
}
|
|
9815
9971
|
}
|
|
9816
9972
|
async function runRefresh(opts) {
|
|
9973
|
+
return refreshWith(opts, false);
|
|
9974
|
+
}
|
|
9975
|
+
async function refreshWith(opts, grantRetried) {
|
|
9817
9976
|
const baseURL = opts.value.baseURL;
|
|
9818
9977
|
if (baseURL === void 0) {
|
|
9819
9978
|
await opts.state.patch({ unset: ["refreshRequest"] });
|
|
@@ -9850,6 +10009,28 @@ async function runRefresh(opts) {
|
|
|
9850
10009
|
return null;
|
|
9851
10010
|
} catch (error) {
|
|
9852
10011
|
const refreshError = toLoginError(error, "\u65E0\u6CD5\u8FDE\u63A5\u7F51\u5173\uFF0C\u8BF7\u68C0\u67E5 baseURL \u6216\u7F51\u7EDC");
|
|
10012
|
+
if (refreshError.code === "SESSION_EXPIRED" && !grantRetried) {
|
|
10013
|
+
const grant = await opts.credentials.resolve(REFRESH_TOKEN_REF).catch(() => void 0);
|
|
10014
|
+
if (grant !== void 0 && grant.value !== "") {
|
|
10015
|
+
try {
|
|
10016
|
+
const renewed = await opts.gateway.refreshSession(grant.value);
|
|
10017
|
+
await opts.credentials.set(SESSION_REF, renewed.sessionCookie);
|
|
10018
|
+
if (renewed.refreshToken === void 0) await opts.credentials.unset(REFRESH_TOKEN_REF).catch(() => {
|
|
10019
|
+
});
|
|
10020
|
+
else await opts.credentials.set(REFRESH_TOKEN_REF, renewed.refreshToken);
|
|
10021
|
+
if (renewed.sessionExpiresAt !== void 0) {
|
|
10022
|
+
await opts.state.patch({ set: { sessionExpiresAt: renewed.sessionExpiresAt } });
|
|
10023
|
+
}
|
|
10024
|
+
return refreshWith(opts, true);
|
|
10025
|
+
} catch (grantError) {
|
|
10026
|
+
const code = grantError instanceof GatewayError ? grantError.code : void 0;
|
|
10027
|
+
if (code === "REFRESH_GRANT_INVALID" || code === "REFRESH_GRANT_ABSENT") {
|
|
10028
|
+
await opts.credentials.unset(REFRESH_TOKEN_REF).catch(() => {
|
|
10029
|
+
});
|
|
10030
|
+
}
|
|
10031
|
+
}
|
|
10032
|
+
}
|
|
10033
|
+
}
|
|
9853
10034
|
if (refreshError.code === "SESSION_EXPIRED" && opts.value.rememberPassword === true && opts.value.username !== void 0) {
|
|
9854
10035
|
const remembered = await opts.credentials.resolve(REMEMBERED_PASSWORD_REF).catch(() => void 0);
|
|
9855
10036
|
if (remembered !== void 0) {
|
|
@@ -9874,6 +10055,8 @@ async function runLogout(opts) {
|
|
|
9874
10055
|
});
|
|
9875
10056
|
await opts.credentials.unset(SESSION_REF).catch(() => {
|
|
9876
10057
|
});
|
|
10058
|
+
await opts.credentials.unset(REFRESH_TOKEN_REF).catch(() => {
|
|
10059
|
+
});
|
|
9877
10060
|
await opts.credentials.unset(PENDING_PASSWORD_REF).catch(() => {
|
|
9878
10061
|
});
|
|
9879
10062
|
await opts.credentials.unset(REMEMBERED_PASSWORD_REF).catch(() => {
|
|
@@ -9892,7 +10075,9 @@ async function runLogout(opts) {
|
|
|
9892
10075
|
"lastError",
|
|
9893
10076
|
"keyId",
|
|
9894
10077
|
"budgets",
|
|
9895
|
-
"keys"
|
|
10078
|
+
"keys",
|
|
10079
|
+
// 会话寿命随会话一起清空:残留的旧 expiresAt 会让保活决策基于已失效的会话。
|
|
10080
|
+
"sessionExpiresAt"
|
|
9896
10081
|
]
|
|
9897
10082
|
});
|
|
9898
10083
|
}
|
|
@@ -12490,7 +12675,7 @@ var Service = class Service2 {
|
|
|
12490
12675
|
}
|
|
12491
12676
|
};
|
|
12492
12677
|
|
|
12493
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-scope@0.
|
|
12678
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-scope@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4_@deepseek-ai+dsh-invariants_8ef32aa4891a716d53102df556bb759f/node_modules/@deepseek-ai/dsh-scope/lib/index.js
|
|
12494
12679
|
var NamedEntries = class {
|
|
12495
12680
|
duplicateError;
|
|
12496
12681
|
data = /* @__PURE__ */ new Map();
|
|
@@ -12706,10 +12891,10 @@ function scopeTarget(base, key) {
|
|
|
12706
12891
|
return carrier;
|
|
12707
12892
|
}
|
|
12708
12893
|
|
|
12709
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-llm@0.
|
|
12894
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-llm@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-llm/lib/index.js
|
|
12710
12895
|
import { createRequire } from "node:module";
|
|
12711
12896
|
|
|
12712
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.
|
|
12897
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-typert-protocol/lib/index.js
|
|
12713
12898
|
var RemoteError = class extends Error {
|
|
12714
12899
|
code;
|
|
12715
12900
|
details;
|
|
@@ -12834,7 +13019,7 @@ function validateName(subject, value) {
|
|
|
12834
13019
|
if (!isTypertRemoteSegment(value)) throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`);
|
|
12835
13020
|
}
|
|
12836
13021
|
|
|
12837
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.
|
|
13022
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-values/lib/index.js
|
|
12838
13023
|
function assertNever(value, context) {
|
|
12839
13024
|
const rendered = JSON.stringify(value) ?? String(value);
|
|
12840
13025
|
throw new Error(`unreachable variant${context ? ` in ${context}` : ""}: ${rendered}`);
|
|
@@ -12843,7 +13028,7 @@ function hasIntrinsicConstructor(prototype, name2) {
|
|
|
12843
13028
|
const constructor = Object.getOwnPropertyDescriptor(prototype, "constructor")?.value;
|
|
12844
13029
|
if (typeof constructor !== "function") return false;
|
|
12845
13030
|
try {
|
|
12846
|
-
return constructor.name === name2 && constructor.prototype === prototype && Function.prototype.toString.call(constructor) ===
|
|
13031
|
+
return constructor.name === name2 && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === Function.prototype.toString.call(name2 === "Array" ? Array : Object);
|
|
12847
13032
|
} catch {
|
|
12848
13033
|
return false;
|
|
12849
13034
|
}
|
|
@@ -13015,7 +13200,7 @@ function deepFreeze(value) {
|
|
|
13015
13200
|
return value;
|
|
13016
13201
|
}
|
|
13017
13202
|
|
|
13018
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-util-crypto@0.
|
|
13203
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-util-crypto@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-crypto/lib/index.js
|
|
13019
13204
|
function randomUUID2() {
|
|
13020
13205
|
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
13021
13206
|
const hex = Array.from(bytes, (byte, index) => {
|
|
@@ -13024,15 +13209,15 @@ function randomUUID2() {
|
|
|
13024
13209
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
13025
13210
|
}
|
|
13026
13211
|
|
|
13027
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-brand@0.
|
|
13212
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-brand@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-brand/lib/index.js
|
|
13028
13213
|
function brandString(value) {
|
|
13029
13214
|
return value;
|
|
13030
13215
|
}
|
|
13031
13216
|
|
|
13032
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-timeout@0.
|
|
13217
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-timeout@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-timeout/lib/index.js
|
|
13033
13218
|
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
13034
13219
|
|
|
13035
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-llm@0.
|
|
13220
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-llm@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-llm/lib/index.js
|
|
13036
13221
|
function freezeMessage(message) {
|
|
13037
13222
|
return deepFreeze(structuredClone(message));
|
|
13038
13223
|
}
|
|
@@ -14075,7 +14260,7 @@ function adapterFailureChunk(error, signal) {
|
|
|
14075
14260
|
};
|
|
14076
14261
|
}
|
|
14077
14262
|
|
|
14078
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-sandbox@0.
|
|
14263
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-sandbox@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4_@deepseek-ai+dsh-llm@0.2._910788faa6d5e8808178f15deb98d164/node_modules/@deepseek-ai/dsh-sandbox/lib/index.js
|
|
14079
14264
|
var WIDER_MODES = {
|
|
14080
14265
|
"read-only": ["workspace-write", "danger-full-access"],
|
|
14081
14266
|
"workspace-write": ["danger-full-access"]
|
|
@@ -14117,7 +14302,7 @@ async function approveEscalation(request, approval) {
|
|
|
14117
14302
|
}
|
|
14118
14303
|
}
|
|
14119
14304
|
|
|
14120
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-tools@0.
|
|
14305
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-tools@0.2.0-rc.1_44958e8f826516598aa7d335d84aa068/node_modules/@deepseek-ai/dsh-tools/lib/index.js
|
|
14121
14306
|
var JsonSchemaError = class extends HarnessError {
|
|
14122
14307
|
/** Individual schema violations in walk order. */
|
|
14123
14308
|
violations;
|
|
@@ -18504,6 +18689,140 @@ async function readJson2(response) {
|
|
|
18504
18689
|
}
|
|
18505
18690
|
}
|
|
18506
18691
|
|
|
18692
|
+
// src/session-fanout.ts
|
|
18693
|
+
function buildSessionFanout(handlers) {
|
|
18694
|
+
const entries = [
|
|
18695
|
+
["client policy", handlers.onPolicyRefresh],
|
|
18696
|
+
["managed mcp", handlers.onManagedMcpRefresh],
|
|
18697
|
+
["managed skills", handlers.onManagedSkillsRefresh],
|
|
18698
|
+
["workbench", handlers.onWorkbenchRefresh]
|
|
18699
|
+
];
|
|
18700
|
+
return () => {
|
|
18701
|
+
for (const [label, run] of entries) {
|
|
18702
|
+
try {
|
|
18703
|
+
run();
|
|
18704
|
+
} catch (error) {
|
|
18705
|
+
handlers.log?.(`hiwork-core: \u4F1A\u8BDD\u8054\u52A8\u5237\u65B0\u300C${label}\u300D\u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
18706
|
+
}
|
|
18707
|
+
}
|
|
18708
|
+
};
|
|
18709
|
+
}
|
|
18710
|
+
|
|
18711
|
+
// src/session-supervisor.ts
|
|
18712
|
+
var SESSION_TTL_ASSUMPTION_MS = 24 * 60 * 6e4;
|
|
18713
|
+
var SESSION_CHECK_INTERVAL_MS = 60 * 6e4;
|
|
18714
|
+
var SESSION_RECOVERY_COOLDOWN_MS = 6e4;
|
|
18715
|
+
var SessionSupervisor = class {
|
|
18716
|
+
constructor(deps) {
|
|
18717
|
+
this.deps = deps;
|
|
18718
|
+
}
|
|
18719
|
+
timer;
|
|
18720
|
+
/** 上次「已知会话存活」的时刻;undefined = 本进程内还没确认过(重启后的首次检查照打)。 */
|
|
18721
|
+
lastAuthedSuccessAt;
|
|
18722
|
+
/**
|
|
18723
|
+
* 最近一次带会话成功响应里 `X-Session-Expires-At` 给出的**内存**寿命估计(原样时刻串)。
|
|
18724
|
+
* 只活在内存里——热路径绝不写 settings(Review Focus 5),只有心跳成功才落盘。
|
|
18725
|
+
*/
|
|
18726
|
+
lastHeaderExpiresAt;
|
|
18727
|
+
/** 恢复请求是否在途(单飞去抖)。 */
|
|
18728
|
+
recoveryInFlight = false;
|
|
18729
|
+
/** 上次触发恢复的时刻(冷却窗口基准)。 */
|
|
18730
|
+
lastRecoveryAt;
|
|
18731
|
+
/** 开始兜底检查;重复调用不叠加定时器。 */
|
|
18732
|
+
start() {
|
|
18733
|
+
if (this.timer !== void 0) return;
|
|
18734
|
+
this.timer = setInterval(() => {
|
|
18735
|
+
void this.wake();
|
|
18736
|
+
}, SESSION_CHECK_INTERVAL_MS);
|
|
18737
|
+
this.timer.unref?.();
|
|
18738
|
+
}
|
|
18739
|
+
/** 停止兜底检查(调用后零活动)。 */
|
|
18740
|
+
stop() {
|
|
18741
|
+
if (this.timer === void 0) return;
|
|
18742
|
+
clearInterval(this.timer);
|
|
18743
|
+
this.timer = void 0;
|
|
18744
|
+
}
|
|
18745
|
+
/**
|
|
18746
|
+
* 带会话的请求成功 → 记活动时间(由 ai-router-client 的活动汇聚驱动)。
|
|
18747
|
+
* `expiresAt` 为响应头 `X-Session-Expires-At` 给出的会话寿命:**只更新内存估计**,
|
|
18748
|
+
* 绝不在此写 settings——热路径上每个成功请求都写盘会打爆设置面(Review Focus 5)。
|
|
18749
|
+
* 不可解析的值直接丢弃(当作没给),不覆盖既有估计。
|
|
18750
|
+
*/
|
|
18751
|
+
noteAuthedSuccess(expiresAt) {
|
|
18752
|
+
this.lastAuthedSuccessAt = this.now();
|
|
18753
|
+
if (expiresAt !== void 0 && !Number.isNaN(Date.parse(expiresAt))) this.lastHeaderExpiresAt = expiresAt;
|
|
18754
|
+
}
|
|
18755
|
+
/**
|
|
18756
|
+
* 带会话的请求收到 401 → 去抖后触发一次会话恢复。
|
|
18757
|
+
* 去抖有两层:`recoveryInFlight`(单飞,覆盖「恢复请求还没落地,同刻又来了 5 条 401」)
|
|
18758
|
+
* 与 `SESSION_RECOVERY_COOLDOWN_MS` 冷却(覆盖恢复完成后短时间内的余波 401)。
|
|
18759
|
+
* 恢复失败只记日志——apply 后写入面需要几秒才就绪,那一侧的失败不该惊动宿主。
|
|
18760
|
+
*/
|
|
18761
|
+
reportAuthed401(source) {
|
|
18762
|
+
if (this.recoveryInFlight) return;
|
|
18763
|
+
const now = this.now();
|
|
18764
|
+
if (this.lastRecoveryAt !== void 0 && now - this.lastRecoveryAt < SESSION_RECOVERY_COOLDOWN_MS) return;
|
|
18765
|
+
this.recoveryInFlight = true;
|
|
18766
|
+
this.lastRecoveryAt = now;
|
|
18767
|
+
void this.deps.requestRecovery().catch(() => {
|
|
18768
|
+
this.log(`hiwork-core: \u4F1A\u8BDD\u6062\u590D\u89E6\u53D1\u5931\u8D25\uFF08\u6765\u6E90 ${source}\uFF09\uFF0C\u7B49\u5F85\u4E0B\u4E2A 401 \u6216\u5FC3\u8DF3\u91CD\u8BD5`);
|
|
18769
|
+
}).finally(() => {
|
|
18770
|
+
this.recoveryInFlight = false;
|
|
18771
|
+
});
|
|
18772
|
+
}
|
|
18773
|
+
now() {
|
|
18774
|
+
return this.deps.now?.() ?? Date.now();
|
|
18775
|
+
}
|
|
18776
|
+
log(message) {
|
|
18777
|
+
this.deps.log?.(message);
|
|
18778
|
+
}
|
|
18779
|
+
/**
|
|
18780
|
+
* 一次兜底检查。判定顺序(早退即不发请求):
|
|
18781
|
+
* 无会话 / 无 baseURL → 返回;距上次已认证成功不足 TTL/2 → 返回;
|
|
18782
|
+
* 已知剩余寿命 > TTL/2 → 返回;否则 ping。
|
|
18783
|
+
* 寿命未知也 ping——重启后的首次检查即校验会话是否还活着。
|
|
18784
|
+
* 「已知剩余寿命」取 settings 值与内存估计(响应头)的**较大者**:头值只会更晚更准,
|
|
18785
|
+
* 用较大者才不会因为 settings 里的旧估算偏早而白打心跳。
|
|
18786
|
+
*/
|
|
18787
|
+
async wake() {
|
|
18788
|
+
try {
|
|
18789
|
+
const session = await this.deps.getSession();
|
|
18790
|
+
if (session === void 0 || session === "") return;
|
|
18791
|
+
if (this.deps.getBaseURL() === void 0) return;
|
|
18792
|
+
const now = this.now();
|
|
18793
|
+
if (this.lastAuthedSuccessAt !== void 0 && now - this.lastAuthedSuccessAt < SESSION_TTL_ASSUMPTION_MS / 2) return;
|
|
18794
|
+
const knownExpiresAtMs = this.knownExpiresAtMs();
|
|
18795
|
+
if (knownExpiresAtMs !== void 0 && knownExpiresAtMs - now > SESSION_TTL_ASSUMPTION_MS / 2) return;
|
|
18796
|
+
let pinged;
|
|
18797
|
+
try {
|
|
18798
|
+
pinged = await this.deps.ping(session);
|
|
18799
|
+
} catch (error) {
|
|
18800
|
+
const expired = error instanceof GatewayError && error.code === "SESSION_EXPIRED";
|
|
18801
|
+
this.log(expired ? "hiwork-core: \u4F1A\u8BDD\u5FC3\u8DF3\u53D1\u73B0\u4F1A\u8BDD\u5DF2\u5931\u6548\uFF0C\u7B49\u5F85 401 \u6C47\u805A\u89E6\u53D1\u6062\u590D" : "hiwork-core: \u4F1A\u8BDD\u5FC3\u8DF3\u8BF7\u6C42\u5931\u8D25\uFF0C\u5C06\u5728\u4E0B\u4E2A\u5468\u671F\u91CD\u8BD5");
|
|
18802
|
+
return;
|
|
18803
|
+
}
|
|
18804
|
+
const pingedExpiresAt = pinged?.expiresAt;
|
|
18805
|
+
const pingedMs = pingedExpiresAt === void 0 ? Number.NaN : Date.parse(pingedExpiresAt);
|
|
18806
|
+
const nextExpiresAt = pingedExpiresAt === void 0 || Number.isNaN(pingedMs) ? new Date(this.now() + SESSION_TTL_ASSUMPTION_MS).toISOString() : pingedExpiresAt;
|
|
18807
|
+
try {
|
|
18808
|
+
await this.deps.patchSessionExpiresAt(nextExpiresAt);
|
|
18809
|
+
} catch {
|
|
18810
|
+
this.log("hiwork-core: \u4F1A\u8BDD\u5FC3\u8DF3\u6210\u529F\u4F46\u5BFF\u547D\u56DE\u5199\u5931\u8D25\uFF0C\u5C06\u5728\u4E0B\u4E2A\u5468\u671F\u91CD\u8BD5");
|
|
18811
|
+
}
|
|
18812
|
+
} catch {
|
|
18813
|
+
this.log("hiwork-core: \u4F1A\u8BDD\u5FC3\u8DF3\u68C0\u67E5\u5931\u8D25\uFF0C\u5C06\u5728\u4E0B\u4E2A\u5468\u671F\u91CD\u8BD5");
|
|
18814
|
+
}
|
|
18815
|
+
}
|
|
18816
|
+
/**
|
|
18817
|
+
* 已知的会话到期时刻(epoch ms):settings 值与内存头值里**有效且较晚**的那个;
|
|
18818
|
+
* 两者都没有(或都不可解析)返回 undefined = 寿命未知。
|
|
18819
|
+
*/
|
|
18820
|
+
knownExpiresAtMs() {
|
|
18821
|
+
const values = [this.deps.getSessionExpiresAt(), this.lastHeaderExpiresAt].map((iso) => iso === void 0 ? Number.NaN : Date.parse(iso)).filter((ms) => !Number.isNaN(ms));
|
|
18822
|
+
return values.length === 0 ? void 0 : Math.max(...values);
|
|
18823
|
+
}
|
|
18824
|
+
};
|
|
18825
|
+
|
|
18507
18826
|
// src/pms-todo-bridge.ts
|
|
18508
18827
|
var PMS_TODO_RPC_CHANNEL = "/hiwork-pms-todo";
|
|
18509
18828
|
var PMS_TODO_RPC_ENDPOINTS = [
|
|
@@ -19132,6 +19451,70 @@ function provideIdentity(ctx, deps) {
|
|
|
19132
19451
|
};
|
|
19133
19452
|
}
|
|
19134
19453
|
|
|
19454
|
+
// src/identity-context.ts
|
|
19455
|
+
var IDENTITY_CONTEXT_NAME = "hiwork:identity";
|
|
19456
|
+
var IDENTITY_CONTEXT_ORDER = 105;
|
|
19457
|
+
var CAVEAT = "\u8BE5\u8EAB\u4EFD\u7528\u4E8E\u4E2A\u6027\u5316\u4E0E\u6309\u4EBA\u8868\u8FF0\uFF1B\u6D89\u53CA\u6570\u636E\u6743\u9650\u7684\u64CD\u4F5C\u5FC5\u987B\u8D70\u53D7\u7BA1\u5DE5\u5177/\u8FDE\u63A5\u5668\u5B8C\u6210\uFF0C\u4E0D\u5F97\u628A\u6B64\u6587\u672C\u5F53\u4F5C\u51ED\u8BC1\u3002";
|
|
19458
|
+
function textOrUndefined6(value) {
|
|
19459
|
+
if (typeof value !== "string") return void 0;
|
|
19460
|
+
const text = value.trim();
|
|
19461
|
+
return text === "" ? void 0 : text;
|
|
19462
|
+
}
|
|
19463
|
+
function renderIdentityContextText(state) {
|
|
19464
|
+
const username = textOrUndefined6(state?.username);
|
|
19465
|
+
if (username === void 0) return "";
|
|
19466
|
+
const displayName = textOrUndefined6(state?.displayName);
|
|
19467
|
+
const who = displayName === void 0 ? `\u5DE5\u53F7 ${username}` : `${displayName}\uFF08\u5DE5\u53F7 ${username}\uFF09`;
|
|
19468
|
+
return `HiWork \u767B\u5F55\u8EAB\u4EFD\uFF1A${who}\u3002${CAVEAT}`;
|
|
19469
|
+
}
|
|
19470
|
+
function registerIdentityContext(systemPrompt, deps) {
|
|
19471
|
+
const dispose = systemPrompt.context({
|
|
19472
|
+
name: IDENTITY_CONTEXT_NAME,
|
|
19473
|
+
order: IDENTITY_CONTEXT_ORDER,
|
|
19474
|
+
text: () => {
|
|
19475
|
+
try {
|
|
19476
|
+
if (!deps.enabled()) return "";
|
|
19477
|
+
return renderIdentityContextText(deps.current());
|
|
19478
|
+
} catch (error) {
|
|
19479
|
+
deps.log?.(
|
|
19480
|
+
`hiwork-core: \u767B\u5F55\u8EAB\u4EFD\u4E0A\u4E0B\u6587\u8BFB\u53D6\u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`
|
|
19481
|
+
);
|
|
19482
|
+
return "";
|
|
19483
|
+
}
|
|
19484
|
+
}
|
|
19485
|
+
});
|
|
19486
|
+
return typeof dispose === "function" ? dispose : () => {
|
|
19487
|
+
};
|
|
19488
|
+
}
|
|
19489
|
+
|
|
19490
|
+
// src/ttl-cache.ts
|
|
19491
|
+
var TtlCache = class {
|
|
19492
|
+
ttlMs;
|
|
19493
|
+
entry;
|
|
19494
|
+
constructor(opts) {
|
|
19495
|
+
this.ttlMs = opts.ttlMs;
|
|
19496
|
+
}
|
|
19497
|
+
/** 命中返回缓存值;会话键不同或已到期返回 undefined。`now` 可注入(缺省 Date.now)。 */
|
|
19498
|
+
get(sessionKey, now = Date.now()) {
|
|
19499
|
+
const hit = this.entry;
|
|
19500
|
+
if (hit === void 0 || hit.sessionKey !== sessionKey) return void 0;
|
|
19501
|
+
if (now - hit.at >= this.ttlMs) return void 0;
|
|
19502
|
+
return hit.value;
|
|
19503
|
+
}
|
|
19504
|
+
/** 写入/覆盖缓存(新会话键会顶掉旧会话那条)。 */
|
|
19505
|
+
put(sessionKey, value, now = Date.now()) {
|
|
19506
|
+
this.entry = { sessionKey, value, at: now };
|
|
19507
|
+
}
|
|
19508
|
+
/** 清掉指定会话键的条目(不影响别的键,虽然只会存在一条);不传参数则清空。 */
|
|
19509
|
+
invalidate(sessionKey) {
|
|
19510
|
+
if (sessionKey === void 0) {
|
|
19511
|
+
this.entry = void 0;
|
|
19512
|
+
return;
|
|
19513
|
+
}
|
|
19514
|
+
if (this.entry?.sessionKey === sessionKey) this.entry = void 0;
|
|
19515
|
+
}
|
|
19516
|
+
};
|
|
19517
|
+
|
|
19135
19518
|
// src/knowledge-config.ts
|
|
19136
19519
|
var HIWORK_KNOWLEDGE_SERVICE = "hiworkKnowledge";
|
|
19137
19520
|
var ME_KNOWLEDGE_CONFIG_PATH = "/api/me/knowledge-config";
|
|
@@ -19158,22 +19541,22 @@ function messageFor(reason) {
|
|
|
19158
19541
|
function failure12(reason, message) {
|
|
19159
19542
|
return { ok: false, reason, message: message ?? messageFor(reason) };
|
|
19160
19543
|
}
|
|
19161
|
-
function
|
|
19544
|
+
function textOrUndefined7(value) {
|
|
19162
19545
|
if (typeof value !== "string") return void 0;
|
|
19163
19546
|
const text = value.trim();
|
|
19164
19547
|
return text === "" ? void 0 : text;
|
|
19165
19548
|
}
|
|
19166
19549
|
function projectKnowledgeConfig(body) {
|
|
19167
|
-
const baseUrl =
|
|
19168
|
-
const apiKey =
|
|
19550
|
+
const baseUrl = textOrUndefined7(body["base_url"] ?? body["baseUrl"]);
|
|
19551
|
+
const apiKey = textOrUndefined7(body["api_key"] ?? body["apiKey"]);
|
|
19169
19552
|
if (baseUrl === void 0 || apiKey === void 0) return void 0;
|
|
19170
19553
|
return {
|
|
19171
19554
|
ok: true,
|
|
19172
19555
|
baseUrl,
|
|
19173
19556
|
apiKey,
|
|
19174
|
-
agentId:
|
|
19175
|
-
chatModelId:
|
|
19176
|
-
tenantId:
|
|
19557
|
+
agentId: textOrUndefined7(body["agent_id"] ?? body["agentId"]) ?? "",
|
|
19558
|
+
chatModelId: textOrUndefined7(body["chat_model_id"] ?? body["chatModelId"]) ?? "",
|
|
19559
|
+
tenantId: textOrUndefined7(body["tenant_id"] ?? body["tenantId"]) ?? "",
|
|
19177
19560
|
knowledgeBases: projectKnowledgeBases(body["knowledge_bases"] ?? body["knowledgeBases"])
|
|
19178
19561
|
};
|
|
19179
19562
|
}
|
|
@@ -19184,10 +19567,10 @@ function projectKnowledgeBases(value) {
|
|
|
19184
19567
|
for (const item of value) {
|
|
19185
19568
|
if (item === null || typeof item !== "object") continue;
|
|
19186
19569
|
const record = item;
|
|
19187
|
-
const id =
|
|
19570
|
+
const id = textOrUndefined7(record["id"]);
|
|
19188
19571
|
if (id === void 0 || seen.has(id)) continue;
|
|
19189
19572
|
seen.add(id);
|
|
19190
|
-
bases.push({ id, name:
|
|
19573
|
+
bases.push({ id, name: textOrUndefined7(record["name"]) ?? "" });
|
|
19191
19574
|
}
|
|
19192
19575
|
return bases.length === 0 ? EMPTY_KNOWLEDGE_BASES : bases;
|
|
19193
19576
|
}
|
|
@@ -19220,8 +19603,9 @@ var KnowledgeConfigProvider = class {
|
|
|
19220
19603
|
constructor(deps) {
|
|
19221
19604
|
this.deps = deps;
|
|
19222
19605
|
}
|
|
19223
|
-
|
|
19224
|
-
|
|
19606
|
+
configCache = new TtlCache({ ttlMs: KNOWLEDGE_CONFIG_TTL_MS });
|
|
19607
|
+
// 令牌缓存比配置缓存短 30s(KNOWLEDGE_TOKEN_CACHE_TTL_MS 已扣掉余量,见其注释)。
|
|
19608
|
+
tokenCache = new TtlCache({ ttlMs: KNOWLEDGE_TOKEN_CACHE_TTL_MS });
|
|
19225
19609
|
async token(opts) {
|
|
19226
19610
|
const force = opts?.force === true;
|
|
19227
19611
|
let sessionCookie;
|
|
@@ -19232,9 +19616,9 @@ var KnowledgeConfigProvider = class {
|
|
|
19232
19616
|
return failure12("error");
|
|
19233
19617
|
}
|
|
19234
19618
|
if (!sessionCookie) return failure12("unauthenticated");
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
return hit
|
|
19619
|
+
if (!force) {
|
|
19620
|
+
const hit = this.tokenCache.get(sessionCookie, this.now());
|
|
19621
|
+
if (hit !== void 0) return hit;
|
|
19238
19622
|
}
|
|
19239
19623
|
const gateway = this.deps.gateway();
|
|
19240
19624
|
if (!gateway) return failure12("unreachable");
|
|
@@ -19243,8 +19627,8 @@ var KnowledgeConfigProvider = class {
|
|
|
19243
19627
|
const raw = await gateway.getMyKnowledgeToken(sessionCookie);
|
|
19244
19628
|
const envelope = raw;
|
|
19245
19629
|
const body = envelope?.["data"] && typeof envelope["data"] === "object" ? envelope["data"] : envelope;
|
|
19246
|
-
const token =
|
|
19247
|
-
const audience =
|
|
19630
|
+
const token = textOrUndefined7(body?.["token"] ?? body?.["knowledge_token"]);
|
|
19631
|
+
const audience = textOrUndefined7(body?.["audience"] ?? body?.["aud"]);
|
|
19248
19632
|
const ids = body?.["knowledge_base_ids"] ?? body?.["knowledgeBaseIds"];
|
|
19249
19633
|
if (!token || audience !== "hiwork-knowledge" || !Array.isArray(ids) || !ids.every((id) => typeof id === "string")) {
|
|
19250
19634
|
this.deps.log?.("hiwork-core: \u7F51\u5173\u8FD4\u56DE\u7684 knowledge-token \u5F62\u72B6\u65E0\u6548");
|
|
@@ -19255,11 +19639,11 @@ var KnowledgeConfigProvider = class {
|
|
|
19255
19639
|
const knowledgeBases = Array.isArray(rawBases) ? rawBases.flatMap((item) => {
|
|
19256
19640
|
if (item === null || typeof item !== "object") return [];
|
|
19257
19641
|
const obj = item;
|
|
19258
|
-
const id =
|
|
19259
|
-
return id ? [{ id, name:
|
|
19642
|
+
const id = textOrUndefined7(obj["id"]);
|
|
19643
|
+
return id ? [{ id, name: textOrUndefined7(obj["name"]) ?? "" }] : [];
|
|
19260
19644
|
}).filter((item) => knowledgeBaseIds.includes(item.id)) : [];
|
|
19261
19645
|
const view = { ok: true, token, audience, knowledgeBaseIds, knowledgeBases };
|
|
19262
|
-
this.
|
|
19646
|
+
this.tokenCache.put(sessionCookie, view, this.now());
|
|
19263
19647
|
return view;
|
|
19264
19648
|
} catch (error) {
|
|
19265
19649
|
const mapped = reasonOfErrorCode(error);
|
|
@@ -19279,10 +19663,8 @@ var KnowledgeConfigProvider = class {
|
|
|
19279
19663
|
}
|
|
19280
19664
|
if (sessionCookie === void 0 || sessionCookie === "") return failure12("unauthenticated");
|
|
19281
19665
|
if (!force) {
|
|
19282
|
-
const hit = this.
|
|
19283
|
-
if (hit !== void 0
|
|
19284
|
-
return hit.view;
|
|
19285
|
-
}
|
|
19666
|
+
const hit = this.configCache.get(sessionCookie, this.now());
|
|
19667
|
+
if (hit !== void 0) return hit;
|
|
19286
19668
|
}
|
|
19287
19669
|
const gateway = this.deps.gateway();
|
|
19288
19670
|
if (gateway === void 0) return failure12("unreachable");
|
|
@@ -19305,7 +19687,7 @@ var KnowledgeConfigProvider = class {
|
|
|
19305
19687
|
this.deps.log?.("hiwork-core: \u7F51\u5173\u8FD4\u56DE\u7684 knowledge-config \u4E0D\u5B8C\u6574\uFF08\u7F3A base_url / api_key \u4E4B\u4E00\uFF09");
|
|
19306
19688
|
return failure12("error");
|
|
19307
19689
|
}
|
|
19308
|
-
this.
|
|
19690
|
+
this.configCache.put(sessionCookie, view, this.now());
|
|
19309
19691
|
return view;
|
|
19310
19692
|
}
|
|
19311
19693
|
now() {
|
|
@@ -19374,7 +19756,7 @@ function messageFor2(reason) {
|
|
|
19374
19756
|
function failure13(reason, message) {
|
|
19375
19757
|
return { ok: false, reason, message: message ?? messageFor2(reason) };
|
|
19376
19758
|
}
|
|
19377
|
-
function
|
|
19759
|
+
function textOrUndefined8(value) {
|
|
19378
19760
|
if (typeof value !== "string") return void 0;
|
|
19379
19761
|
const text = value.trim();
|
|
19380
19762
|
return text === "" ? void 0 : text;
|
|
@@ -19383,15 +19765,15 @@ function teamIdsOf(value) {
|
|
|
19383
19765
|
if (!Array.isArray(value)) return [];
|
|
19384
19766
|
const ids = [];
|
|
19385
19767
|
for (const item of value) {
|
|
19386
|
-
const text =
|
|
19768
|
+
const text = textOrUndefined8(item);
|
|
19387
19769
|
if (text !== void 0) ids.push(text);
|
|
19388
19770
|
}
|
|
19389
19771
|
return ids;
|
|
19390
19772
|
}
|
|
19391
19773
|
function projectMemoryConfig(body) {
|
|
19392
|
-
const panelUrl =
|
|
19393
|
-
const serviceId =
|
|
19394
|
-
const apiKey =
|
|
19774
|
+
const panelUrl = textOrUndefined8(body["panel_url"] ?? body["panelUrl"]);
|
|
19775
|
+
const serviceId = textOrUndefined8(body["service_id"] ?? body["serviceId"]);
|
|
19776
|
+
const apiKey = textOrUndefined8(body["api_key"] ?? body["apiKey"] ?? body["userKey"]);
|
|
19395
19777
|
if (panelUrl === void 0 || serviceId === void 0 || apiKey === void 0) return void 0;
|
|
19396
19778
|
return {
|
|
19397
19779
|
ok: true,
|
|
@@ -19429,7 +19811,7 @@ var MemoryConfigProvider = class {
|
|
|
19429
19811
|
constructor(deps) {
|
|
19430
19812
|
this.deps = deps;
|
|
19431
19813
|
}
|
|
19432
|
-
|
|
19814
|
+
cache = new TtlCache({ ttlMs: MEMORY_CONFIG_TTL_MS });
|
|
19433
19815
|
async config(opts) {
|
|
19434
19816
|
const force = opts?.force === true;
|
|
19435
19817
|
let sessionCookie;
|
|
@@ -19441,10 +19823,8 @@ var MemoryConfigProvider = class {
|
|
|
19441
19823
|
}
|
|
19442
19824
|
if (sessionCookie === void 0 || sessionCookie === "") return failure13("unauthenticated");
|
|
19443
19825
|
if (!force) {
|
|
19444
|
-
const hit = this.
|
|
19445
|
-
if (hit !== void 0
|
|
19446
|
-
return hit.view;
|
|
19447
|
-
}
|
|
19826
|
+
const hit = this.cache.get(sessionCookie, this.now());
|
|
19827
|
+
if (hit !== void 0) return hit;
|
|
19448
19828
|
}
|
|
19449
19829
|
const gateway = this.deps.gateway();
|
|
19450
19830
|
if (gateway === void 0) return failure13("unreachable", MESSAGE_NO_GATEWAY);
|
|
@@ -19467,7 +19847,7 @@ var MemoryConfigProvider = class {
|
|
|
19467
19847
|
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");
|
|
19468
19848
|
return failure13("error");
|
|
19469
19849
|
}
|
|
19470
|
-
this.
|
|
19850
|
+
this.cache.put(sessionCookie, view, this.now());
|
|
19471
19851
|
return view;
|
|
19472
19852
|
}
|
|
19473
19853
|
now() {
|
|
@@ -19658,7 +20038,7 @@ function provideOfficeRelay(ctx, deps) {
|
|
|
19658
20038
|
};
|
|
19659
20039
|
}
|
|
19660
20040
|
|
|
19661
|
-
// node_modules/.pnpm/@deepseek-ai+dsh-web@0.
|
|
20041
|
+
// node_modules/.pnpm/@deepseek-ai+dsh-web@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4_@deepseek-ai+dsh-llm@0.2.0-rc.1_@deepseek-ai+cordis@4.0.4_/node_modules/@deepseek-ai/dsh-web/lib/index.js
|
|
19662
20042
|
var WebError = class extends HarnessError {
|
|
19663
20043
|
};
|
|
19664
20044
|
var WebRuntime = class extends Service {
|
|
@@ -19836,7 +20216,7 @@ function httpOutcomeToError(status, code) {
|
|
|
19836
20216
|
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);
|
|
19837
20217
|
return new WebError("\u8054\u7F51\u641C\u7D22\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", "WEB_PROVIDER_ERROR");
|
|
19838
20218
|
}
|
|
19839
|
-
function
|
|
20219
|
+
function textOrUndefined9(value) {
|
|
19840
20220
|
if (typeof value !== "string") return void 0;
|
|
19841
20221
|
const text = value.trim();
|
|
19842
20222
|
return text === "" ? void 0 : text;
|
|
@@ -19848,11 +20228,11 @@ function projectWebSearch(body) {
|
|
|
19848
20228
|
for (const item of raw) {
|
|
19849
20229
|
if (item === null || typeof item !== "object") continue;
|
|
19850
20230
|
const record = item;
|
|
19851
|
-
const url =
|
|
20231
|
+
const url = textOrUndefined9(record["url"]);
|
|
19852
20232
|
if (url === void 0) continue;
|
|
19853
|
-
const title =
|
|
19854
|
-
const snippet =
|
|
19855
|
-
const publishedAt =
|
|
20233
|
+
const title = textOrUndefined9(record["title"]);
|
|
20234
|
+
const snippet = textOrUndefined9(record["snippet"]) ?? textOrUndefined9(record["content"]);
|
|
20235
|
+
const publishedAt = textOrUndefined9(record["published_at"]);
|
|
19856
20236
|
sources.push({
|
|
19857
20237
|
url,
|
|
19858
20238
|
...title !== void 0 ? { title } : {},
|
|
@@ -19916,7 +20296,7 @@ function registerManagedSearchProvider(web, deps) {
|
|
|
19916
20296
|
|
|
19917
20297
|
// src/index.ts
|
|
19918
20298
|
var name = "hiwork-core";
|
|
19919
|
-
var inject = ["settings", "credentials", "workspaceRegistry", "connection", "web", "agents"];
|
|
20299
|
+
var inject = ["settings", "credentials", "workspaceRegistry", "connection", "web", "agents", "systemPrompt"];
|
|
19920
20300
|
var NS = "ai-router";
|
|
19921
20301
|
var PI_AI_NS = "llm-pi-ai";
|
|
19922
20302
|
var MenuConfig = Schema.object({
|
|
@@ -19928,9 +20308,12 @@ var MenuConfig = Schema.object({
|
|
|
19928
20308
|
var lastErrorSchema = Schema.object({ code: Schema.string().required(), message: Schema.string().required() }).default(void 0);
|
|
19929
20309
|
var Config = Schema.object({
|
|
19930
20310
|
baseURL: Schema.string(),
|
|
20311
|
+
// 非 volatile:与 baseURL 同类的组合层固定配置(不进用户表单),出问题经 bundle patch 关闭。
|
|
20312
|
+
identityContext: Schema.boolean().default(true),
|
|
19931
20313
|
keyId: Schema.string().volatile(),
|
|
19932
20314
|
username: Schema.string().volatile(),
|
|
19933
20315
|
displayName: Schema.string().volatile(),
|
|
20316
|
+
sessionExpiresAt: Schema.string().volatile(),
|
|
19934
20317
|
lastLogin: Schema.object({ at: Schema.string().required(), modelCount: Schema.number().required(), gatewayName: Schema.string().required() }).default(void 0).volatile(),
|
|
19935
20318
|
lastError: lastErrorSchema.volatile(),
|
|
19936
20319
|
pendingLogin: Schema.object({ username: Schema.string().required(), passwordRef: Schema.string().required() }).default(void 0).volatile(),
|
|
@@ -20285,22 +20668,60 @@ function apply(ctx, config) {
|
|
|
20285
20668
|
}
|
|
20286
20669
|
};
|
|
20287
20670
|
let inFlight;
|
|
20288
|
-
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
|
|
20295
|
-
baseURL
|
|
20296
|
-
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
|
|
20671
|
+
const sessionSupervisor = new SessionSupervisor({
|
|
20672
|
+
getSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
20673
|
+
getSessionExpiresAt: () => current().sessionExpiresAt,
|
|
20674
|
+
getBaseURL: () => current().baseURL,
|
|
20675
|
+
ping: async (sessionCookie) => {
|
|
20676
|
+
const baseURL = current().baseURL;
|
|
20677
|
+
if (baseURL === void 0 || baseURL === "") throw new Error("baseURL \u672A\u914D\u7F6E\uFF0C\u8DF3\u8FC7\u4F1A\u8BDD\u5FC3\u8DF3");
|
|
20678
|
+
const sessions = await gatewayFor(baseURL).listSessions(sessionCookie);
|
|
20679
|
+
const expiresAt = sessions.find((item) => item.current === true && item.expires_at !== void 0)?.expires_at;
|
|
20680
|
+
return expiresAt === void 0 ? {} : { expiresAt };
|
|
20681
|
+
},
|
|
20682
|
+
patchSessionExpiresAt: (iso) => ports.state.patch({ set: { sessionExpiresAt: iso } }),
|
|
20683
|
+
requestRecovery: () => ports.state.patch({ set: { refreshRequest: { at: (/* @__PURE__ */ new Date()).toISOString() } } }),
|
|
20684
|
+
log: (message) => {
|
|
20685
|
+
ctx.logger.warn(message);
|
|
20686
|
+
}
|
|
20687
|
+
});
|
|
20688
|
+
const sessionActivitySink2 = (event) => {
|
|
20689
|
+
if (event.kind === "success") sessionSupervisor.noteAuthedSuccess(event.expiresAt);
|
|
20690
|
+
else sessionSupervisor.reportAuthed401("gateway");
|
|
20303
20691
|
};
|
|
20692
|
+
ctx.effect(() => {
|
|
20693
|
+
setSessionActivitySink(sessionActivitySink2);
|
|
20694
|
+
sessionSupervisor.start();
|
|
20695
|
+
return () => {
|
|
20696
|
+
sessionSupervisor.stop();
|
|
20697
|
+
clearSessionActivitySink(sessionActivitySink2);
|
|
20698
|
+
};
|
|
20699
|
+
}, "hiwork-core: session supervisor");
|
|
20700
|
+
const policyPoller = createClientPolicyPoller({
|
|
20701
|
+
attempt: async () => {
|
|
20702
|
+
const baseURL = current().baseURL;
|
|
20703
|
+
if (baseURL === void 0 || baseURL === "") return false;
|
|
20704
|
+
let fetched = false;
|
|
20705
|
+
await projectLoginMode({
|
|
20706
|
+
baseURL,
|
|
20707
|
+
credentials: ports.credentials,
|
|
20708
|
+
state: ports.state,
|
|
20709
|
+
fetchPolicy: async (input) => {
|
|
20710
|
+
const policy = await fetchClientPolicy(input);
|
|
20711
|
+
fetched = policy !== void 0;
|
|
20712
|
+
return policy;
|
|
20713
|
+
},
|
|
20714
|
+
log: (message) => {
|
|
20715
|
+
ctx.logger.warn(message);
|
|
20716
|
+
}
|
|
20717
|
+
});
|
|
20718
|
+
return fetched;
|
|
20719
|
+
},
|
|
20720
|
+
log: (message) => {
|
|
20721
|
+
ctx.logger.warn(message);
|
|
20722
|
+
}
|
|
20723
|
+
});
|
|
20724
|
+
let notifySessionProvisioned;
|
|
20304
20725
|
const dispatchSectionChange = () => {
|
|
20305
20726
|
const value = current();
|
|
20306
20727
|
const requested = value.pendingLogin ?? value.browserLoginRequest ?? value.refreshRequest ?? value.logoutRequest;
|
|
@@ -20317,6 +20738,7 @@ function apply(ctx, config) {
|
|
|
20317
20738
|
ctx.logger.warn(message);
|
|
20318
20739
|
}
|
|
20319
20740
|
});
|
|
20741
|
+
if (value.pendingLogin !== void 0 || value.refreshRequest !== void 0) notifySessionProvisioned?.();
|
|
20320
20742
|
} catch (error) {
|
|
20321
20743
|
ctx.logger.error("hiwork-core: ai-router section change failed", error);
|
|
20322
20744
|
if (isHmrNestedWriteError(error)) {
|
|
@@ -20339,7 +20761,7 @@ function apply(ctx, config) {
|
|
|
20339
20761
|
};
|
|
20340
20762
|
ctx.effect(() => {
|
|
20341
20763
|
const consume = () => {
|
|
20342
|
-
|
|
20764
|
+
policyPoller.trigger();
|
|
20343
20765
|
dispatchSectionChange();
|
|
20344
20766
|
};
|
|
20345
20767
|
consume();
|
|
@@ -20347,6 +20769,7 @@ function apply(ctx, config) {
|
|
|
20347
20769
|
timer.unref?.();
|
|
20348
20770
|
return () => {
|
|
20349
20771
|
clearInterval(timer);
|
|
20772
|
+
policyPoller.dispose();
|
|
20350
20773
|
};
|
|
20351
20774
|
}, "hiwork-core: login request poll");
|
|
20352
20775
|
void ctx.root.loader.await().then(() => importLegacyMenuSection({
|
|
@@ -20356,7 +20779,7 @@ function apply(ctx, config) {
|
|
|
20356
20779
|
})).catch((error) => {
|
|
20357
20780
|
ctx.logger.warn(`hiwork-core: \u65E7\u7248\u83DC\u5355\u504F\u597D\u8FC1\u79FB\u672A\u6267\u884C\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
20358
20781
|
});
|
|
20359
|
-
|
|
20782
|
+
policyPoller.trigger();
|
|
20360
20783
|
void (async () => {
|
|
20361
20784
|
for (const delay2 of STALE_BROWSER_LOGIN_RECONCILE_DELAYS_MS) {
|
|
20362
20785
|
if (delay2 > 0) await new Promise((resolve3) => {
|
|
@@ -20561,6 +20984,27 @@ function apply(ctx, config) {
|
|
|
20561
20984
|
clearInterval(timer);
|
|
20562
20985
|
};
|
|
20563
20986
|
}, "hiwork-core: workbench warmup");
|
|
20987
|
+
notifySessionProvisioned = buildSessionFanout({
|
|
20988
|
+
onPolicyRefresh: () => policyPoller.trigger(),
|
|
20989
|
+
onManagedMcpRefresh: () => {
|
|
20990
|
+
void managedMcp.load().catch((error) => {
|
|
20991
|
+
ctx.logger.warn(`hiwork-core: \u4F1A\u8BDD\u4F9B\u7ED9\u540E\u5237\u65B0\u53D7\u7BA1 MCP \u6E05\u5355\u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
20992
|
+
});
|
|
20993
|
+
},
|
|
20994
|
+
onManagedSkillsRefresh: () => {
|
|
20995
|
+
void managedSkills.load().catch((error) => {
|
|
20996
|
+
ctx.logger.warn(`hiwork-core: \u4F1A\u8BDD\u4F9B\u7ED9\u540E\u5237\u65B0\u53D7\u7BA1\u6280\u80FD\u6E05\u5355\u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
20997
|
+
});
|
|
20998
|
+
},
|
|
20999
|
+
onWorkbenchRefresh: () => {
|
|
21000
|
+
void workbench.load().catch((error) => {
|
|
21001
|
+
ctx.logger.warn(`hiwork-core: \u4F1A\u8BDD\u4F9B\u7ED9\u540E\u5237\u65B0\u5DE5\u4F5C\u53F0\u6E05\u5355\u5931\u8D25\uFF08${error instanceof Error ? error.name : typeof error}\uFF09`);
|
|
21002
|
+
});
|
|
21003
|
+
},
|
|
21004
|
+
log: (message) => {
|
|
21005
|
+
ctx.logger.warn(message);
|
|
21006
|
+
}
|
|
21007
|
+
});
|
|
20564
21008
|
const pmsTodoDeps = {
|
|
20565
21009
|
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
20566
21010
|
gateway: () => {
|
|
@@ -20599,6 +21043,13 @@ function apply(ctx, config) {
|
|
|
20599
21043
|
ctx.logger.warn(message);
|
|
20600
21044
|
}
|
|
20601
21045
|
}), "hiwork-core: identity service");
|
|
21046
|
+
ctx.effect(() => registerIdentityContext(ctx.systemPrompt, {
|
|
21047
|
+
current: () => current(),
|
|
21048
|
+
enabled: () => current().identityContext !== false,
|
|
21049
|
+
log: (message) => {
|
|
21050
|
+
ctx.logger.warn(message);
|
|
21051
|
+
}
|
|
21052
|
+
}), "hiwork-core: identity runtime context");
|
|
20602
21053
|
ctx.effect(() => provideMemoryConfig(ctx, {
|
|
20603
21054
|
resolveSession: async () => (await ports.credentials.resolve(SESSION_REF))?.value,
|
|
20604
21055
|
gateway: () => {
|
|
@@ -20664,9 +21115,9 @@ function apply(ctx, config) {
|
|
|
20664
21115
|
}), "hiwork-core: plugin updates rpc");
|
|
20665
21116
|
ctx.effect(() => registerIpcMessageHandler({
|
|
20666
21117
|
source: process,
|
|
20667
|
-
complete: (input) => {
|
|
21118
|
+
complete: async (input) => {
|
|
20668
21119
|
const value = current();
|
|
20669
|
-
|
|
21120
|
+
const result = await completeBrowserLogin(input, {
|
|
20670
21121
|
...ports,
|
|
20671
21122
|
value,
|
|
20672
21123
|
gateway: gatewayFor(value.baseURL ?? ""),
|
|
@@ -20674,6 +21125,8 @@ function apply(ctx, config) {
|
|
|
20674
21125
|
ctx.logger.warn(message);
|
|
20675
21126
|
}
|
|
20676
21127
|
});
|
|
21128
|
+
if (result === null) notifySessionProvisioned?.();
|
|
21129
|
+
return result;
|
|
20677
21130
|
},
|
|
20678
21131
|
setDevice: (info) => {
|
|
20679
21132
|
setDeviceInfo(info);
|