@chatcode/cco-llm-chatcode-config 0.1.0 → 0.1.2
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/README.md +5 -5
- package/README.zh.md +6 -6
- package/lib/client.js +41 -19
- package/lib/index.js +8 -5
- package/lib/index.js.map +1 -1
- package/package.json +8 -9
- package/vendor/dsh-llm-pi-ai/src/config.ts +1 -1
- package/vendor/dsh-llm-pi-ai/tests/adapter.spec.ts +10 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
This plugin publishes
|
|
12
|
+
This plugin publishes CodingPlan and optional Yuanjing model catalogs, provides shared ChatCode account access, and reports committed ChatCode CLI Session activity to ChatCode. Legacy user-defined routes remain runtime-compatible but are not exposed through Web or CLI configuration. Runtime model credentials stay in the Host process, while the account grant stays in ChatCode CLI credential storage and never reaches Web or TUI clients. Reporting is enabled by default and can be disabled with `reporting.enabled: false`.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -62,9 +62,9 @@ The `llm-chatcode-config` section in `$CHATCODE_CLI_HOME/settings.yaml` is the r
|
|
|
62
62
|
chatCodeSession: true
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
MAAS has a different response shape from CodingPlan: the catalog returns model IDs, and the plugin resolves each ID through its private runtime endpoint. `codingPlanEndpoint` and `catalogTimeoutMs` override the CodingPlan address and catalog timeout.
|
|
65
|
+
Yuanjing (internally identified by the legacy MAAS setting) has a different response shape from CodingPlan: the catalog returns model IDs, and the plugin resolves each ID through its private runtime endpoint. `codingPlanEndpoint` and `catalogTimeoutMs` override the CodingPlan address and catalog timeout.
|
|
66
66
|
|
|
67
|
-
The package also ships a browser client bundle. Its **Model configuration** card contains only the
|
|
67
|
+
The package also ships a browser client bundle. Its **Model configuration** card contains only the user-facing **Yuanjing** switch; it does not expose or edit the `customModels` array, and it does not display CodingPlan and managed-model rows. The browser decodes only the legacy internal `enableMaas` field from the redacted settings view and never needs custom-model API keys.
|
|
68
68
|
|
|
69
69
|
-----
|
|
70
70
|
|
|
@@ -106,10 +106,10 @@ The model receives the normal ChatCode CLI system prompt, messages, and tools th
|
|
|
106
106
|
|
|
107
107
|
<a id="known-limitations-and-deferred-work"></a>
|
|
108
108
|
|
|
109
|
-
- Managed catalog reads are activation snapshots; remount or restart after changing a central catalog. The
|
|
109
|
+
- Managed catalog reads are activation snapshots; remount or restart after changing a central catalog. The Yuanjing switch refreshes its selector group immediately.
|
|
110
110
|
- Imported models declare text input. Non-DeepSeek routes do not expose selectable reasoning effort.
|
|
111
111
|
- One invalid entry, including a duplicate model ID, suppresses the complete imported catalog; the bundle does not publish a partially valid source.
|
|
112
|
-
- The public plugin client extension point adds this package's managed-model configuration card to the native Models page. The card controls
|
|
112
|
+
- The public plugin client extension point adds this package's managed-model configuration card to the native Models page. The card controls Yuanjing only; user-defined model configuration is not exposed, while CodingPlan and Yuanjing groups remain read-only.
|
|
113
113
|
- The package tracks the copied pi-ai adapter source and the native DeepSeek adapter peer; upgrade either through an explicit compatibility test, and refresh `vendor/` when pi-ai changes.
|
|
114
114
|
- Conversation synchronization has no durable outbox, and ChatCode message requests are not retried when the server may have committed them.
|
|
115
115
|
|
package/README.zh.md
CHANGED
|
@@ -10,9 +10,9 @@ kind: "package-bundle"
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
此插件发布 CodingPlan 与可选元景模型目录,提供共用 ChatCode 账号访问,并向 ChatCode 上报已提交的 ChatCode CLI Session 活动。历史版本写入的用户自定义路由仅保留运行时兼容,不再通过 Web 或 CLI 暴露配置入口。运行时模型凭据只保存在 Host 进程中,账号 grant 保存在 ChatCode CLI 凭据存储中且不会进入 Web 或 TUI 客户端。上报默认开启,可通过 `reporting.enabled: false` 关闭。
|
|
14
14
|
|
|
15
|
-
启动时还会读取 Coding Plan
|
|
15
|
+
启动时还会读取 Coding Plan 运行时模型接口,并在会话模型选择器中按 `内置模型`、(启用后)`元景`、`自定义模型` 的顺序发布三个独立分组。接口返回的 API Key 只保存在进程内的请求鉴权对象中;模型列表、日志和错误信息不会包含该值。
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
## 目录
|
|
@@ -71,9 +71,9 @@ MAAS 默认关闭。开启后,插件先读取 `https://chatcode.chinaunicom.cn
|
|
|
71
71
|
maasEndpoint: https://chatcode.chinaunicom.cn/cvp/wanma/api/v1/cli/maas-models
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
MAAS
|
|
74
|
+
元景(内部仍沿用旧 MAAS 配置标识)目录接口与 Coding Plan 接口的返回结构不同:目录接口返回模型 ID,插件会再按 ID 获取私有运行配置。可用 `codingPlanEndpoint` 和 `catalogTimeoutMs` 覆盖 Coding Plan 地址和读取超时。
|
|
75
75
|
|
|
76
|
-
本包同时发布浏览器 client bundle
|
|
76
|
+
本包同时发布浏览器 client bundle,在原生“模型”设置页增加“模型配置”卡片,仅保留“元景”开关,不展示 CodingPlan 或元景模型列表,也不暴露或编辑 `customModels`。浏览器只从脱敏设置视图中解析内部兼容字段 `enableMaas`,无需获取自定义模型的 API key。
|
|
77
77
|
|
|
78
78
|
-----
|
|
79
79
|
|
|
@@ -115,10 +115,10 @@ DeepSeek 路由使用条目中的协议、基础 URL 和 API key。其 OpenAI
|
|
|
115
115
|
|
|
116
116
|
<a id="known-limitations-and-deferred-work"></a>
|
|
117
117
|
|
|
118
|
-
- 中央目录读取为激活快照;更新中央目录后需要重新挂载或重启 profile
|
|
118
|
+
- 中央目录读取为激活快照;更新中央目录后需要重新挂载或重启 profile。元景开关会立即刷新会话选择分组。
|
|
119
119
|
- 导入模型声明文本输入。非 DeepSeek 路由不公开可选推理强度。
|
|
120
120
|
- 任一条目非法(包括模型 ID 重复)都会抑制完整导入目录;bundle 不会发布部分有效的来源。
|
|
121
|
-
- 公共插件 client
|
|
121
|
+
- 公共插件 client 扩展点允许本包向原生“模型”页面追加托管模型配置卡片。该卡片只控制元景;用户自定义模型配置不再暴露,CodingPlan 与元景分组保持只读。
|
|
122
122
|
- 包会同时跟踪复制的 pi-ai 适配器源码和原生 DeepSeek 适配器 peer;升级任一实现都必须执行显式兼容性测试,pi-ai 变化时还需刷新 `vendor/`。
|
|
123
123
|
- 会话同步没有持久化 outbox;当服务端可能已经提交时,ChatCode 消息请求不会重试。
|
|
124
124
|
|
package/lib/client.js
CHANGED
|
@@ -12,7 +12,7 @@ window.__ModuleLoader__.load({
|
|
|
12
12
|
max-width: 720px;
|
|
13
13
|
flex-direction: column;
|
|
14
14
|
gap: 20px;
|
|
15
|
-
margin-top:
|
|
15
|
+
margin-top: 0;
|
|
16
16
|
color: var(--dsw-alias-label-primary);
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -357,29 +357,45 @@ window.__ModuleLoader__.load({
|
|
|
357
357
|
background: var(--dsw-alias-fill-secondary);
|
|
358
358
|
}
|
|
359
359
|
`;
|
|
360
|
+
//#endregion
|
|
361
|
+
//#region src/client/settings.ts
|
|
362
|
+
/**
|
|
363
|
+
* Decode only the non-secret field rendered by the browser card. The Host
|
|
364
|
+
* redacts custom-model API keys, so validating the complete Config schema in
|
|
365
|
+
* the browser would reject otherwise valid custom-model rows.
|
|
366
|
+
* @param section - redacted namespace value received from the Host.
|
|
367
|
+
* @returns the MAAS projection, or undefined when its field is invalid.
|
|
368
|
+
*/
|
|
369
|
+
function decodeMaasSettings(section) {
|
|
370
|
+
if (typeof section !== "object" || section === null || Array.isArray(section)) return void 0;
|
|
371
|
+
const enableMaas = Reflect.get(section, "enableMaas");
|
|
372
|
+
return typeof enableMaas === "boolean" ? { enableMaas } : void 0;
|
|
373
|
+
}
|
|
360
374
|
//#endregion
|
|
361
375
|
//#region src/client/index.ts
|
|
362
|
-
/** Browser extension
|
|
376
|
+
/** Browser extension replacing the Models settings section with the Yuanjing switch. */
|
|
363
377
|
const React = require("react");
|
|
364
378
|
const SETTINGS_NAMESPACE = "llm-chatcode-config";
|
|
365
379
|
const LOG_PREFIX = "[dsh-llm-chatcode-config]";
|
|
366
380
|
const en = {
|
|
381
|
+
nav: "Models",
|
|
367
382
|
title: "Model configuration",
|
|
368
|
-
description: "
|
|
369
|
-
maas: "
|
|
370
|
-
maasDescription: "
|
|
371
|
-
maasToggle: "
|
|
372
|
-
maasUpdating: "Updating
|
|
373
|
-
maasUnavailable: "
|
|
383
|
+
description: "CodingPlan and Yuanjing models remain available in the conversation model selector.",
|
|
384
|
+
maas: "Yuanjing",
|
|
385
|
+
maasDescription: "Show Yuanjing models in the conversation model selector.",
|
|
386
|
+
maasToggle: "Yuanjing",
|
|
387
|
+
maasUpdating: "Updating Yuanjing…",
|
|
388
|
+
maasUnavailable: "Yuanjing setting is unavailable."
|
|
374
389
|
};
|
|
375
390
|
const zh = {
|
|
391
|
+
nav: "模型",
|
|
376
392
|
title: "模型配置",
|
|
377
|
-
description: "
|
|
378
|
-
maas: "
|
|
379
|
-
maasDescription: "
|
|
380
|
-
maasToggle: "
|
|
381
|
-
maasUpdating: "
|
|
382
|
-
maasUnavailable: "
|
|
393
|
+
description: "CodingPlan 与元景模型会在对话模型选择中提供。",
|
|
394
|
+
maas: "元景",
|
|
395
|
+
maasDescription: "开启后,元景模型会出现在对话模型选择中。",
|
|
396
|
+
maasToggle: "元景",
|
|
397
|
+
maasUpdating: "正在更新元景…",
|
|
398
|
+
maasUnavailable: "元景设置不可用。"
|
|
383
399
|
};
|
|
384
400
|
function installStyles() {
|
|
385
401
|
const documentRef = globalThis.document;
|
|
@@ -430,7 +446,10 @@ window.__ModuleLoader__.load({
|
|
|
430
446
|
zh,
|
|
431
447
|
en
|
|
432
448
|
}), "chatcode-models: dictionaries");
|
|
433
|
-
const scope = ctx.settingsScope.bind({
|
|
449
|
+
const scope = ctx.settingsScope.bind({
|
|
450
|
+
namespace: SETTINGS_NAMESPACE,
|
|
451
|
+
decode: decodeMaasSettings
|
|
452
|
+
});
|
|
434
453
|
ctx.effect(() => {
|
|
435
454
|
let previous = "";
|
|
436
455
|
const report = () => {
|
|
@@ -448,11 +467,14 @@ window.__ModuleLoader__.load({
|
|
|
448
467
|
return scope.subscribe(report);
|
|
449
468
|
}, "chatcode-models: settings diagnostics");
|
|
450
469
|
const t = ctx.locale.bind("settings.chatcodeModels");
|
|
451
|
-
ctx.slots.inject("settings.
|
|
452
|
-
console.info(`${LOG_PREFIX}
|
|
470
|
+
ctx.slots.inject("settings.section", () => {
|
|
471
|
+
console.info(`${LOG_PREFIX} replacing settings.section models entry`);
|
|
453
472
|
return ctx.slots.register({
|
|
454
|
-
name: "settings.
|
|
455
|
-
id: "
|
|
473
|
+
name: "settings.section",
|
|
474
|
+
id: "models",
|
|
475
|
+
order: 10,
|
|
476
|
+
priority: -100,
|
|
477
|
+
label: () => t("nav"),
|
|
456
478
|
locale: "settings.chatcodeModels",
|
|
457
479
|
inject: () => ({
|
|
458
480
|
scope,
|
package/lib/index.js
CHANGED
|
@@ -441,7 +441,6 @@ async function validatePackage(config, packageName, options) {
|
|
|
441
441
|
const url = validateUrl(config.cvpChatCodeApiUrl);
|
|
442
442
|
url.searchParams.set("packageName", packageName);
|
|
443
443
|
url.searchParams.set("versionNum", versionNum);
|
|
444
|
-
console.log(`[version-check] 开始校验 ${packageName}@${versionNum}`);
|
|
445
444
|
const request = options.request ?? fetch;
|
|
446
445
|
let response;
|
|
447
446
|
try {
|
|
@@ -1398,7 +1397,7 @@ function buildProvider(spec) {
|
|
|
1398
1397
|
//#endregion
|
|
1399
1398
|
//#region vendor/dsh-llm-pi-ai/src/config.ts
|
|
1400
1399
|
/** Default maximum idle interval while an adapter stream read is outstanding. */
|
|
1401
|
-
const DEFAULT_STREAM_IDLE_TIMEOUT_MS =
|
|
1400
|
+
const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 6e5;
|
|
1402
1401
|
/**
|
|
1403
1402
|
* Default request-level bound on base64-encoded image payload. Every image in
|
|
1404
1403
|
* history is re-encoded into every request body, so an unbounded conversation
|
|
@@ -1559,7 +1558,7 @@ function resolveProfiles(providers) {
|
|
|
1559
1558
|
if (provider.length === 0) throw new Error("llm-pi-ai: provider names must be non-empty");
|
|
1560
1559
|
if (source.baseURL !== void 0 && source.baseURL.length === 0) throw new Error(`llm-pi-ai: provider "${provider}" has an empty baseURL`);
|
|
1561
1560
|
if (source.displayName !== void 0 && source.displayName.length === 0) throw new Error(`llm-pi-ai: provider "${provider}" has an empty displayName`);
|
|
1562
|
-
const streamIdleTimeoutMs = source.streamIdleTimeoutMs ??
|
|
1561
|
+
const streamIdleTimeoutMs = source.streamIdleTimeoutMs ?? 6e5;
|
|
1563
1562
|
if (!Number.isFinite(streamIdleTimeoutMs) || streamIdleTimeoutMs <= 0 || streamIdleTimeoutMs > MAX_TIMER_DELAY_MS) throw new Error(`llm-pi-ai: provider "${provider}" streamIdleTimeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
|
|
1564
1563
|
const maxRequestImageBytes = source.maxRequestImageBytes ?? 20971520;
|
|
1565
1564
|
if (!Number.isInteger(maxRequestImageBytes) || maxRequestImageBytes <= 0) throw new Error(`llm-pi-ai: provider "${provider}" maxRequestImageBytes must be a positive integer`);
|
|
@@ -2394,7 +2393,7 @@ const CODING_PLAN_PROVIDER = "chatcode-codingplan";
|
|
|
2394
2393
|
const CODING_PLAN_PROVIDER_NAME = "内置模型";
|
|
2395
2394
|
/** Provider route and selector group for opt-in MAAS models. */
|
|
2396
2395
|
const MAAS_PROVIDER = "chatcode-maas";
|
|
2397
|
-
const MAAS_PROVIDER_NAME = "
|
|
2396
|
+
const MAAS_PROVIDER_NAME = "元景";
|
|
2398
2397
|
const DEEPSEEK_MODEL = /deepseek/i;
|
|
2399
2398
|
function privateModelKey(route, model) {
|
|
2400
2399
|
return `${route}\u0000${model}`;
|
|
@@ -4785,6 +4784,10 @@ async function apply(ctx, config) {
|
|
|
4785
4784
|
throw error;
|
|
4786
4785
|
}
|
|
4787
4786
|
}));
|
|
4787
|
+
if (customRegistration !== void 0) {
|
|
4788
|
+
customRegistration();
|
|
4789
|
+
customRegistration = void 0;
|
|
4790
|
+
}
|
|
4788
4791
|
for (const entry of loaded) {
|
|
4789
4792
|
if (entry === void 0) continue;
|
|
4790
4793
|
const registration = register(entry.catalog.provider, entry.catalog.name, entry.source);
|
|
@@ -4793,6 +4796,7 @@ async function apply(ctx, config) {
|
|
|
4793
4796
|
managedSources.set(entry.catalog.provider, entry.source);
|
|
4794
4797
|
}
|
|
4795
4798
|
}
|
|
4799
|
+
refreshCustom();
|
|
4796
4800
|
};
|
|
4797
4801
|
const refreshManaged = () => {
|
|
4798
4802
|
if (refreshInFlight !== void 0) return refreshInFlight;
|
|
@@ -4864,7 +4868,6 @@ async function apply(ctx, config) {
|
|
|
4864
4868
|
ctx.logger.warn("chatcode-config: legacy settingsPath is unavailable or invalid; custom models were not imported and import will retry when the Host starts again");
|
|
4865
4869
|
}
|
|
4866
4870
|
});
|
|
4867
|
-
refreshCustom();
|
|
4868
4871
|
await refreshManaged();
|
|
4869
4872
|
}
|
|
4870
4873
|
//#endregion
|