hiwork-core 0.0.29 → 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/lib/client.js +70 -9
- package/lib/index.js +1 -1
- package/lib/types/client/voice/entry.d.ts +29 -3
- package/package.json +2 -2
- package/lib/types/client/daily-items.d.ts +0 -25
package/lib/client.js
CHANGED
|
@@ -5032,6 +5032,15 @@ var VOICE_INPUT_SLOT = "conversation.input.right";
|
|
|
5032
5032
|
var VOICE_INPUT_SLOT_ID = "hiwork-core-voice";
|
|
5033
5033
|
var VOICE_INPUT_SLOT_ORDER = 10;
|
|
5034
5034
|
var VOICE_ROOT_CLASS = "hiwv-root";
|
|
5035
|
+
var VOICE_GATE_RETRY_DELAYS_MS = [3e3, 1e4, 3e4, 6e4, 18e4];
|
|
5036
|
+
var defaultGateTimer = {
|
|
5037
|
+
after: (ms, fn) => {
|
|
5038
|
+
const id = globalThis.setTimeout(fn, ms);
|
|
5039
|
+
return () => {
|
|
5040
|
+
globalThis.clearTimeout(id);
|
|
5041
|
+
};
|
|
5042
|
+
}
|
|
5043
|
+
};
|
|
5035
5044
|
function createOverlayController(deps) {
|
|
5036
5045
|
let container;
|
|
5037
5046
|
let root;
|
|
@@ -5066,12 +5075,61 @@ async function installVoiceInput(deps) {
|
|
|
5066
5075
|
const doc = deps.document ?? (typeof document === "undefined" ? void 0 : document);
|
|
5067
5076
|
const runtime = createVoiceRuntime(deps.rpc);
|
|
5068
5077
|
const overlay = createOverlayController({ runtime, resolveSessions: deps.resolveSessions, doc });
|
|
5078
|
+
const timer = deps.timer ?? defaultGateTimer;
|
|
5069
5079
|
if (doc !== void 0) ensureVoiceStyle(doc);
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5080
|
+
let enabled = false;
|
|
5081
|
+
let disposed = false;
|
|
5082
|
+
let step = 0;
|
|
5083
|
+
let cancelPending;
|
|
5084
|
+
let probing = false;
|
|
5085
|
+
const clearPending = () => {
|
|
5086
|
+
const cancel = cancelPending;
|
|
5087
|
+
cancelPending = void 0;
|
|
5088
|
+
cancel?.();
|
|
5089
|
+
};
|
|
5090
|
+
const dispose = () => {
|
|
5091
|
+
disposed = true;
|
|
5092
|
+
clearPending();
|
|
5093
|
+
overlay.close();
|
|
5094
|
+
};
|
|
5095
|
+
if (deps.signal !== void 0) {
|
|
5096
|
+
if (deps.signal.aborted) disposed = true;
|
|
5097
|
+
else deps.signal.addEventListener("abort", dispose, { once: true });
|
|
5098
|
+
}
|
|
5099
|
+
const probe = async () => {
|
|
5100
|
+
if (disposed || enabled || probing) return;
|
|
5101
|
+
probing = true;
|
|
5102
|
+
const status = await runtime.status().catch(() => void 0);
|
|
5103
|
+
probing = false;
|
|
5104
|
+
if (disposed || enabled) return;
|
|
5105
|
+
if (status?.enabled === true) {
|
|
5106
|
+
enabled = true;
|
|
5107
|
+
clearPending();
|
|
5108
|
+
deps.registerMic({ open: (sessionId) => overlay.open(sessionId) });
|
|
5109
|
+
return;
|
|
5110
|
+
}
|
|
5111
|
+
const delay = VOICE_GATE_RETRY_DELAYS_MS[step];
|
|
5112
|
+
if (delay === void 0) return;
|
|
5113
|
+
step += 1;
|
|
5114
|
+
cancelPending = timer.after(delay, () => {
|
|
5115
|
+
cancelPending = void 0;
|
|
5116
|
+
void probe().catch(() => void 0);
|
|
5117
|
+
});
|
|
5118
|
+
};
|
|
5119
|
+
const retryNow = () => {
|
|
5120
|
+
if (disposed || enabled) return;
|
|
5121
|
+
clearPending();
|
|
5122
|
+
step = 0;
|
|
5123
|
+
void probe().catch(() => void 0);
|
|
5124
|
+
};
|
|
5125
|
+
await probe();
|
|
5126
|
+
return {
|
|
5127
|
+
get enabled() {
|
|
5128
|
+
return enabled;
|
|
5129
|
+
},
|
|
5130
|
+
retryNow,
|
|
5131
|
+
dispose
|
|
5132
|
+
};
|
|
5075
5133
|
}
|
|
5076
5134
|
|
|
5077
5135
|
// src/client/index.ts
|
|
@@ -5131,9 +5189,9 @@ function apply(ctx) {
|
|
|
5131
5189
|
order: 20,
|
|
5132
5190
|
inject: () => ({ store: sessionCost })
|
|
5133
5191
|
}, SessionCost));
|
|
5192
|
+
let voice;
|
|
5134
5193
|
ctx.effect(() => {
|
|
5135
5194
|
const controller2 = new AbortController();
|
|
5136
|
-
let handle;
|
|
5137
5195
|
void installVoiceInput({
|
|
5138
5196
|
rpc: connection.rpc,
|
|
5139
5197
|
// sessions 不在 inject 列表里(那是可选能力),只能按结构读取;**必须现取**:
|
|
@@ -5156,14 +5214,17 @@ function apply(ctx) {
|
|
|
5156
5214
|
installed.dispose();
|
|
5157
5215
|
return;
|
|
5158
5216
|
}
|
|
5159
|
-
|
|
5217
|
+
voice = installed;
|
|
5160
5218
|
}).catch(() => void 0);
|
|
5161
5219
|
return () => {
|
|
5162
5220
|
controller2.abort();
|
|
5163
|
-
|
|
5164
|
-
|
|
5221
|
+
voice?.dispose();
|
|
5222
|
+
voice = void 0;
|
|
5165
5223
|
};
|
|
5166
5224
|
}, "hiwork-core: voice input");
|
|
5225
|
+
ctx.effect(() => observeAccountChange(controller.inject().hooks.aiRouterCard, () => {
|
|
5226
|
+
voice?.retryNow();
|
|
5227
|
+
}), "hiwork-core: \u767B\u5F55\u540E\u590D\u95EE\u8BED\u97F3\u95E8\u7981");
|
|
5167
5228
|
ctx.effect(() => observeAccountChange(controller.inject().hooks.aiRouterCard, () => {
|
|
5168
5229
|
usage.clear();
|
|
5169
5230
|
sessionCost.clear();
|
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";
|
|
@@ -9,6 +9,20 @@ export declare const VOICE_INPUT_SLOT_ID = "hiwork-core-voice";
|
|
|
9
9
|
export declare const VOICE_INPUT_SLOT_ORDER = 10;
|
|
10
10
|
/** 浮层控制器的容器类名(`document.body` 直挂的那层 div;无样式依赖,仅便于排查)。 */
|
|
11
11
|
export declare const VOICE_ROOT_CLASS = "hiwv-root";
|
|
12
|
+
/**
|
|
13
|
+
* 门禁复问的节拍(毫秒):装配后的第 1..n 次复问间隔,**走完就停**(等 `retryNow`)。
|
|
14
|
+
*
|
|
15
|
+
* 首步短(3s)是刻意的:最常见的场景是「应用刚起来、网关会话还没热」。之后拉长只是
|
|
16
|
+
* 为了兜住网关短时不通。**不能无限轮询**——每次复问都是 Host 打网关的一次真 HTTP
|
|
17
|
+
* (`getMyVoiceConfig`),而「本部署没开语音」是完全正常的状态,无限轮询等于给网关
|
|
18
|
+
* 加一份与用户无关的常驻负载。
|
|
19
|
+
*/
|
|
20
|
+
export declare const VOICE_GATE_RETRY_DELAYS_MS: readonly number[];
|
|
21
|
+
/** 门禁复问的定时器面(单测注入假实现——真定时器会让用例要么等 4 分钟、要么靠假时钟)。 */
|
|
22
|
+
export interface VoiceGateTimer {
|
|
23
|
+
/** `ms` 毫秒后调 `fn`;返回取消函数(已取消 / 已触发后重复调用是空操作)。 */
|
|
24
|
+
after(ms: number, fn: () => void): () => void;
|
|
25
|
+
}
|
|
12
26
|
/** 话筒按钮的注入面:`open` 已经绑好会话 id,组件只需调用它。 */
|
|
13
27
|
export interface VoiceMicInject {
|
|
14
28
|
open: (sessionId?: string) => void;
|
|
@@ -32,15 +46,27 @@ export interface VoiceEntryDeps {
|
|
|
32
46
|
document?: Document | undefined;
|
|
33
47
|
/** 安装作废信号(插件卸载 / HMR 重建时 abort):作废后绝不注册话筒按钮。 */
|
|
34
48
|
signal?: AbortSignal | undefined;
|
|
49
|
+
/** 复问定时器面;缺省用真定时器(测试注入假实现,见 tests/voice-overlay.spec.tsx)。 */
|
|
50
|
+
timer?: VoiceGateTimer | undefined;
|
|
35
51
|
}
|
|
36
|
-
/** 安装结果句柄:`enabled` 是 status
|
|
52
|
+
/** 安装结果句柄:`enabled` 是 status 门禁的**当前**结论,`dispose` 关闭浮层并停掉复问。 */
|
|
37
53
|
export interface VoiceEntryHandle {
|
|
54
|
+
/** 取值器而非快照:后台复问成功后由 false 变 true(调用方按需现读)。 */
|
|
38
55
|
readonly enabled: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* 立刻复问一次 status,并**重新起一轮**复问表。给「登录 / 换账号 / 换 Key」这类外部
|
|
58
|
+
* 事件用:它们能让门禁由关变开,而复问表只覆盖装配后的几分钟。已启用或已作废时是
|
|
59
|
+
* 空操作(幂等)。
|
|
60
|
+
*/
|
|
61
|
+
retryNow(): void;
|
|
39
62
|
dispose(): void;
|
|
40
63
|
}
|
|
41
64
|
/**
|
|
42
|
-
* 安装语音输入:注入样式 → 问 status →
|
|
65
|
+
* 安装语音输入:注入样式 → 问 status → 可用才注册话筒按钮;问不上按表复问。
|
|
66
|
+
*
|
|
67
|
+
* **首个 status 出结果就 resolve**(不等复问表走完):调用方拿到的是一份可用的句柄,
|
|
68
|
+
* 复问在后台继续。等表走完再 resolve 会把调用方吊住最长达 4.7 分钟,插件装载也会跟着卡。
|
|
43
69
|
* @param deps - 安装依赖。
|
|
44
|
-
* @returns 安装句柄(`enabled`
|
|
70
|
+
* @returns 安装句柄(`enabled` 是**当时**的门禁结论,复问成功后会变,见该字段说明)。
|
|
45
71
|
*/
|
|
46
72
|
export declare function installVoiceInput(deps: VoiceEntryDeps): Promise<VoiceEntryHandle>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hiwork-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "HiWork 企业统一登录与模型自动供给插件(ai-router 网关登录,Web 表单,无 CLI 认证)",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -81,4 +81,4 @@
|
|
|
81
81
|
"build": "npm run build:host && npm run build:client",
|
|
82
82
|
"test": "vitest run"
|
|
83
83
|
}
|
|
84
|
-
}
|
|
84
|
+
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 《海普发展纲领》第三版 正文条目库(每日一条 · 按本地日期轮换)。
|
|
3
|
-
* 数据源:★《海普发展纲领》第三版20231121.docx 正文五章全部 ➢ 条目,共 75 条;
|
|
4
|
-
* 层级 = 章(第X章 xxx) → 板块(■ xxx) → 条目(➢ 标题) → 正文段落。
|
|
5
|
-
* 标题与正文逐字取自原文,不做润色改写(生成期经程序化逐字校验)。
|
|
6
|
-
* 内容按条目整体打包进插件;运行时无网络、不读本机 docx。
|
|
7
|
-
*/
|
|
8
|
-
export interface DailyItem {
|
|
9
|
-
/** 章标签,含序数,如「第一章 核心理念」。 */
|
|
10
|
-
readonly chapter: string;
|
|
11
|
-
/** 板块标签,如「海普精神」。 */
|
|
12
|
-
readonly section: string;
|
|
13
|
-
/** 整句条目标题(含冒号前缀),逐字原文,如「海普寓意:HICAP、海之势、普之态」。 */
|
|
14
|
-
readonly title: string;
|
|
15
|
-
/** 冒号前词(无冒号条目为空串),页面小字灰展示。 */
|
|
16
|
-
readonly prefix: string;
|
|
17
|
-
/** 冒号后主体(无冒号条目为整句),页面蓝色渐变大字展示。 */
|
|
18
|
-
readonly main: string;
|
|
19
|
-
/** 条目正文段落(逐字原文,可含子条目式段落)。 */
|
|
20
|
-
readonly paragraphs: readonly string[];
|
|
21
|
-
}
|
|
22
|
-
export declare const DAILY_ITEMS: readonly DailyItem[];
|
|
23
|
-
/** 当日条目序号 = 本地日期纪元日数对条数取模。 */
|
|
24
|
-
export declare function dayIndex(date?: Date): number;
|
|
25
|
-
export declare function pickToday(date?: Date): DailyItem;
|