cortico-provider-humanize 0.1.0 → 0.2.0
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/CHANGELOG.md +9 -0
- package/README.md +19 -13
- package/describe.json +2 -2
- package/package.json +7 -7
- package/src/bridge.ts +11 -1
- package/src/index.ts +20 -5
- package/src/wrap.ts +62 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
**装上就生效,不用再新建端点。**
|
|
6
|
+
|
|
7
|
+
- 你现在用的端点(Coo、Responses 兼容等)直接带上活人感:装好两个扩展、重启一次就行,不用到「模型」页新建、填写、切换。
|
|
8
|
+
- 卸载也不用先切端点:卸掉重启后,端点就是原来的端点,桌宠照常说话。
|
|
9
|
+
- 0.1.0 时手动新建的「活人感」端点照样能用,模块改名为「活人感(旧版端点,不用再新建)」。建议切回原来的端点;以后要卸载本包,必须先切回去。
|
|
10
|
+
- 和 World 之间的桥升到第 3 版:要和 `cortico-world-humanize` 0.2.0 一起用。版本对不上时原样转发,不出错。
|
|
11
|
+
|
|
3
12
|
## 0.1.0
|
|
4
13
|
|
|
5
14
|
第一个公开版本。
|
package/README.md
CHANGED
|
@@ -2,26 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
和 [活人感(cortico-world-humanize)](https://github.com/abbabanana/cortico-world-humanize) 搭配使用的 Cortico provider。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
装上以后,你现在用的模型端点就会带上活人感:你对桌宠说话时,先等活人感 World 想好桌宠此刻的心情,再把心情和你的话一起发给模型。主模型这一轮就带着心事开口,不用先调用 `humanize_feel` 再多跑一轮。
|
|
6
6
|
|
|
7
7
|
- **World 开着**:等心事(最多 5 秒),追加在这一批事件的末尾,然后转发。
|
|
8
|
-
- **World
|
|
9
|
-
-
|
|
8
|
+
- **World 关着,或者那边出了任何错**:原样转发,和没装一样。最坏就是这一轮没有心事,桌宠照常说话。
|
|
9
|
+
- 端点的地址、Key、模型、思考档、价格都不动,还是你原来配的。
|
|
10
10
|
- 只改发出去的那一次请求,会话记录不动。
|
|
11
11
|
|
|
12
12
|
## 安装
|
|
13
13
|
|
|
14
|
-
1.
|
|
15
|
-
2. Coopanion
|
|
16
|
-
3.
|
|
17
|
-
4. 把当前端点切到这个新端点。
|
|
18
|
-
5. 活人感会提醒你系统前缀要刷新:在 World 页把「活人感」关掉再打开一次。
|
|
14
|
+
1. Coopanion 的「扩展」页搜「活人感」,把 `cortico-world-humanize` 和 `cortico-provider-humanize` 都装上。
|
|
15
|
+
2. 重启 Coopanion。
|
|
16
|
+
3. World 页打开「活人感」。如果它已经开着,提示「系统前缀需要刷新」时,把它关掉再打开一次。
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
不用到「模型」页做任何设置。在活人感的「最近 20 轮记录」里看到「经 provider 注入」,就说明生效了。
|
|
19
|
+
|
|
20
|
+
> 不装这个 provider,只装 World 也能用,只是桌宠每次要先调用 `humanize_feel`,多跑一轮。
|
|
21
21
|
|
|
22
22
|
## 卸载
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
「扩展」页卸掉,重启。端点还是原来的端点,不用先做别的。
|
|
25
|
+
|
|
26
|
+
**例外**:如果你用 0.1.0 时在「模型」页新建过「活人感」端点(模块叫「活人感(旧版端点,不用再新建)」),并且当前端点还是它,要**先把当前端点切回原来那个**再卸载,不然 Coopanion 找不到这个模块,桌宠会说不了话。
|
|
27
|
+
|
|
28
|
+
## 从 0.1.0 升级
|
|
29
|
+
|
|
30
|
+
升级后原来的「活人感」端点照样能用。建议在「模型」页切回你原来的端点(比如 `deepseek`),然后可以删掉那个「活人感」端点,以后卸载就不用担心了。切换后在 World 页把活人感关开一次。
|
|
25
31
|
|
|
26
32
|
## 为什么不做推理预填充
|
|
27
33
|
|
|
@@ -29,15 +35,15 @@ DeepSeek 的前缀续写(`/beta`)不允许和工具调用一起用,而桌
|
|
|
29
35
|
|
|
30
36
|
## 市场标签说明
|
|
31
37
|
|
|
32
|
-
- `requires-extension`:要和活人感 World
|
|
38
|
+
- `requires-extension`:要和活人感 World 一起用才有作用,单独装就是原样转发。
|
|
33
39
|
- `experimental`:还在测试,只在少数环境里验证过(Windows、DeepSeek)。
|
|
34
40
|
|
|
35
41
|
## 许可证
|
|
36
42
|
|
|
37
|
-
AGPL-3.0-or-later。它在运行时包住 Coopanion
|
|
43
|
+
AGPL-3.0-or-later。它在运行时包住 Coopanion 自带的端点模块(包括 `cortico-provider-coo`,AGPL-3.0-or-later),所以用同样的许可证。
|
|
38
44
|
|
|
39
45
|
---
|
|
40
46
|
|
|
41
47
|
## English
|
|
42
48
|
|
|
43
|
-
**Humanize provider** pairs with the [Humanize World](https://github.com/abbabanana/cortico-world-humanize).
|
|
49
|
+
**Humanize provider** pairs with the [Humanize World](https://github.com/abbabanana/cortico-world-humanize). Install both and restart; there is nothing to set up. Your current model endpoint then waits for the World to write the pet's inner thought whenever the person speaks, and sends it along with their words, so the main model answers with it in a single round. With the World off, or on any error on the World's side, requests pass through unchanged. Uninstalling needs no preparation, unless you still use an endpoint created with the 0.1.0 "Humanize" module: switch back to your original endpoint first. Licensed under AGPL-3.0-or-later, the same as the Coo connection it wraps.
|
package/describe.json
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"text",
|
|
15
15
|
"image"
|
|
16
16
|
],
|
|
17
|
-
"title": "
|
|
18
|
-
"description": "
|
|
17
|
+
"title": "活人感(旧版端点,不用再新建)",
|
|
18
|
+
"description": "0.1.0 时要手动新建的端点类型,留着给已经这么配过的人。现在装上活人感 provider,你原来的端点就自动带上活人感,不用新建这种端点。",
|
|
19
19
|
"reasoningTiers": [
|
|
20
20
|
{
|
|
21
21
|
"id": "off",
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-provider-humanize",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Cortico provider for Coopanion:
|
|
5
|
+
"description": "Cortico provider for Coopanion: once installed, your existing model endpoint waits for the Humanize World's inner thought and sends it along with the person's words. No endpoint to create or switch",
|
|
6
6
|
"author": "abbabanana",
|
|
7
7
|
"license": "AGPL-3.0-or-later",
|
|
8
8
|
"repository": {
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
"cortico": {
|
|
20
20
|
"kind": "provider",
|
|
21
21
|
"api": 6,
|
|
22
|
-
"displayName": "
|
|
22
|
+
"displayName": "活人感 provider",
|
|
23
23
|
"locales": {
|
|
24
24
|
"zh": {
|
|
25
|
-
"displayName": "
|
|
26
|
-
"description": "
|
|
25
|
+
"displayName": "活人感 provider",
|
|
26
|
+
"description": "「活人感」的加速搭档:让桌宠的心事和你的话一起发给模型,桌宠一轮就开口。必须先装「活人感」,装上重启即可,不用任何设置。\n\n**两个扩展怎么配合**\n\n- **活人感**(World,必装):负责想心事、查 AI 固定句式。单独装就能用。\n- **活人感 provider**(就是本扩展,可选):把心事直接放进发给模型的请求里,省掉桌宠先调工具读心事的那一轮,回复更快。\n- 只装本扩展、不装「活人感」,没有任何作用。\n\n**怎么用**\n\n1. 在扩展页把「活人感」和本扩展都装上。\n2. 重启 Coopanion。\n3. 到 World 页打开「活人感」。如果它本来就开着,按提示把它关掉再打开一次。\n\n**不用去「模型」页做任何事。** 你现在用的模型端点会自动带上活人感,地址、Key、模型都不变。活人感关着时,请求原样发出,和没装一样。\n\n**怎么确认生效**:活人感「提示词」页签里的「最近 20 轮记录」出现「经 provider 注入」。\n\n**卸载**:扩展页卸掉,重启即可。只有一种例外:用 0.1.0 时在「模型」页手动新建过「活人感」端点,而且现在还在用它,要先切回原来的端点再卸载,不然桌宠会说不了话。"
|
|
27
27
|
},
|
|
28
28
|
"en": {
|
|
29
|
-
"displayName": "Humanize
|
|
30
|
-
"description": "
|
|
29
|
+
"displayName": "Humanize provider",
|
|
30
|
+
"description": "A speed-up companion for Humanize: sends the pet's inner thought along with your words, so the pet answers in one round. Requires the Humanize World. Install and restart; nothing to set up.\n\n**How the two extensions fit together**\n\n- **Humanize** (World, required): writes the inner thought and checks stock AI sentence patterns. Works on its own.\n- **Humanize provider** (this one, optional): puts the thought straight into the request sent to the model, saving the round where the pet first calls a tool to read it.\n- This extension alone does nothing.\n\n**Getting started**\n\n1. Install both Humanize and this extension on the Extensions page.\n2. Restart Coopanion.\n3. Turn on Humanize on the World page. If it was already on, turn it off and on once when prompted.\n\n**Nothing to do on the Models page.** Your current model endpoint picks it up automatically; address, key and model stay as they are. With Humanize off, requests go out unchanged.\n\n**Uninstall**: remove it on the Extensions page and restart. One exception: if you created a \"Humanize\" endpoint by hand under 0.1.0 and still use it, switch back to your original endpoint first."
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"tags": ["requires-extension", "experimental"],
|
package/src/bridge.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 与 cortico-world-humanize/src/bridge.ts 约定的同一座桥(那边是定义方,这里只读)。
|
|
3
3
|
* World 没启用时 globalThis 上没有它,provider 就原样转发。
|
|
4
|
+
*
|
|
5
|
+
* 反方向还有一块牌子(PROVIDER_KEY):provider 加载时挂上,告诉 World「我装着,包住了哪些模块」,
|
|
6
|
+
* World 据此判断当前端点是不是走 provider 模式。
|
|
4
7
|
*/
|
|
5
8
|
export const BRIDGE_KEY = Symbol.for('cortico-humanize.bridge');
|
|
6
|
-
export const
|
|
9
|
+
export const PROVIDER_KEY = Symbol.for('cortico-humanize.provider');
|
|
10
|
+
export const BRIDGE_VERSION = 3;
|
|
7
11
|
|
|
8
12
|
export interface MainContext {
|
|
9
13
|
instructions: string;
|
|
@@ -17,6 +21,12 @@ export interface HumanizeBridge {
|
|
|
17
21
|
touch(): void;
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
export interface ProviderMarker {
|
|
25
|
+
version: typeof BRIDGE_VERSION;
|
|
26
|
+
/** 这种端点模块(端点配置里的 kind)是不是被活人感包着。 */
|
|
27
|
+
wraps(kind: string): boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
/** 当前挂着的桥;没有或版本对不上返回 null。 */
|
|
21
31
|
export function bridge(): HumanizeBridge | null {
|
|
22
32
|
const b = (globalThis as Record<symbol, unknown>)[BRIDGE_KEY] as HumanizeBridge | undefined;
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 活人感 provider
|
|
2
|
+
* 活人感 provider。
|
|
3
|
+
*
|
|
4
|
+
* 装上就生效:加载时把已注册的每个端点模块(Coo、Responses 兼容……)的 `create` 包一层
|
|
5
|
+
* (见 wrap.ts),你现在用的端点直接带上活人感,不用新建端点、不用切换。卸掉重启就恢复原样。
|
|
6
|
+
*
|
|
7
|
+
* 另外保留一个 `humanize` 模块(0.1.0 时要手动新建的那种端点),已经这么配过的人不用改;
|
|
8
|
+
* 它包住 Coopanion 自己的 Coo 连接(`coo` 模块,从框架的注册表现取,不按路径 import)。
|
|
3
9
|
*
|
|
4
10
|
* 每次请求:上下文最后一项是刚投递进来的事件帧时,问「活人感」World 要这批事件引出的心事
|
|
5
11
|
* (连同主模型这次的系统前缀和最近上下文,让副 API 知道主模型知道的一切,不管记忆存在哪),
|
|
@@ -15,6 +21,7 @@ import type { GenerateOptions, Generation, ResponseClient } from 'cortico/core/g
|
|
|
15
21
|
import type { Request } from 'cortico/protocol/open-responses/index.ts';
|
|
16
22
|
import { bridge } from './bridge.ts';
|
|
17
23
|
import { capped, contextWithInner, inputWithInner, mainContext, newestFrame } from './inject.ts';
|
|
24
|
+
import { wrapAll } from './wrap.ts';
|
|
18
25
|
|
|
19
26
|
export const HUMANIZE_PROVIDER_ID = 'humanize';
|
|
20
27
|
const WRAPPED = 'coo';
|
|
@@ -24,8 +31,8 @@ const CAP_MS = 5_000;
|
|
|
24
31
|
/** 记住最近这么多帧的心事,之后的请求照样补上,前缀才稳定。 */
|
|
25
32
|
const KEEP = 200;
|
|
26
33
|
|
|
27
|
-
const TITLE = '
|
|
28
|
-
const DESCRIPTION = '
|
|
34
|
+
const TITLE = '活人感(旧版端点,不用再新建)';
|
|
35
|
+
const DESCRIPTION = '0.1.0 时要手动新建的端点类型,留着给已经这么配过的人。现在装上活人感 provider,你原来的端点就自动带上活人感,不用新建这种端点。';
|
|
29
36
|
|
|
30
37
|
/** 被包住的模块:Coo,没有就内建的 Responses 兼容模块。 */
|
|
31
38
|
function wrapped(): ProviderModule {
|
|
@@ -133,9 +140,17 @@ export const HUMANIZE_PROVIDER: ProviderModule = {
|
|
|
133
140
|
}))) as ProviderModule['config'];
|
|
134
141
|
},
|
|
135
142
|
create(name, entry, host): ProviderInstance {
|
|
136
|
-
|
|
137
|
-
return
|
|
143
|
+
// 被包住的 Coo 自己已经被 wrapAll 包过时,不再套第二层
|
|
144
|
+
return withHumanize(wrapped().create(name, entry, host));
|
|
138
145
|
},
|
|
139
146
|
} as ProviderModule;
|
|
140
147
|
|
|
148
|
+
/** 给一个端点实例套上活人感;已经套过就原样返回。 */
|
|
149
|
+
export function withHumanize(instance: ProviderInstance): ProviderInstance {
|
|
150
|
+
if (instance.client instanceof HumanizeClient) return instance;
|
|
151
|
+
return { ...instance, client: new HumanizeClient(instance.client) };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
wrapAll(HUMANIZE_PROVIDER_ID, withHumanize);
|
|
155
|
+
|
|
141
156
|
export default HUMANIZE_PROVIDER;
|
package/src/wrap.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 不用另建端点:装上就把已注册的每个 provider 模块的 `create` 包一层,你现在用的端点直接带上
|
|
3
|
+
* 活人感。World 没启用(桥不在)时,包着的这层原样转发,和没装一样。
|
|
4
|
+
*
|
|
5
|
+
* 扩展的 provider 模块(比如 Coo)可能在本包之后才注册,所以除了包现有的,还接住注册表数组
|
|
6
|
+
* 之后的 `push`(`registerProviderModules` 就地往这个数组里加,不换引用)。
|
|
7
|
+
*
|
|
8
|
+
* 卸掉本包重启后,这层包装自然就没了,端点还是原来的端点,不会说不了话。
|
|
9
|
+
*/
|
|
10
|
+
import { providerModules } from 'cortico/providers/registry.ts';
|
|
11
|
+
import type { ProviderModule } from 'cortico/providers/base.ts';
|
|
12
|
+
import { BRIDGE_VERSION, PROVIDER_KEY, type ProviderMarker } from './bridge.ts';
|
|
13
|
+
|
|
14
|
+
const WRAPPED = Symbol.for('cortico-humanize.wrapped');
|
|
15
|
+
const PUSH_HOOKED = Symbol.for('cortico-humanize.push-hooked');
|
|
16
|
+
|
|
17
|
+
type Wrappable = ProviderModule & { [WRAPPED]?: true };
|
|
18
|
+
|
|
19
|
+
/** 包住一个模块的 create;已经包过、或者是活人感自己的旧模块就跳过。成功返回 true。 */
|
|
20
|
+
function wrapModule(module: Wrappable, skip: string, wrapClient: (instance: ReturnType<ProviderModule['create']>) => ReturnType<ProviderModule['create']>): boolean {
|
|
21
|
+
if (!module || module.id === skip) return false;
|
|
22
|
+
if (module[WRAPPED]) return true;
|
|
23
|
+
const original = module.create;
|
|
24
|
+
if (typeof original !== 'function') return false;
|
|
25
|
+
try {
|
|
26
|
+
const create: ProviderModule['create'] = function (this: unknown, name, entry, host) {
|
|
27
|
+
return wrapClient(original.call(this ?? module, name, entry, host));
|
|
28
|
+
};
|
|
29
|
+
module.create = create;
|
|
30
|
+
module[WRAPPED] = true;
|
|
31
|
+
return module.create === create;
|
|
32
|
+
} catch {
|
|
33
|
+
// 冻结的对象改不了:这个模块就不带活人感,照常工作
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 已经包住的模块 id。 */
|
|
39
|
+
const wrappedKinds = new Set<string>();
|
|
40
|
+
|
|
41
|
+
export function wrapAll(skip: string, wrapClient: (instance: ReturnType<ProviderModule['create']>) => ReturnType<ProviderModule['create']>): void {
|
|
42
|
+
const list = providerModules as ProviderModule[] & { [PUSH_HOOKED]?: true };
|
|
43
|
+
for (const module of list) if (wrapModule(module, skip, wrapClient)) wrappedKinds.add(module.id);
|
|
44
|
+
if (!list[PUSH_HOOKED]) {
|
|
45
|
+
try {
|
|
46
|
+
const push = list.push;
|
|
47
|
+
Object.defineProperty(list, 'push', {
|
|
48
|
+
configurable: true, writable: true, enumerable: false,
|
|
49
|
+
value(this: ProviderModule[], ...items: ProviderModule[]) {
|
|
50
|
+
for (const module of items) if (wrapModule(module, skip, wrapClient)) wrappedKinds.add(module.id);
|
|
51
|
+
return push.apply(this, items);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(list, PUSH_HOOKED, { value: true });
|
|
55
|
+
} catch { /* 接不住就只包现有的 */ }
|
|
56
|
+
}
|
|
57
|
+
const marker: ProviderMarker = {
|
|
58
|
+
version: BRIDGE_VERSION,
|
|
59
|
+
wraps: (kind) => kind === skip || wrappedKinds.has(kind),
|
|
60
|
+
};
|
|
61
|
+
(globalThis as Record<symbol, unknown>)[PROVIDER_KEY] = marker;
|
|
62
|
+
}
|