lark-remote 0.5.18 → 0.5.20
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 +32 -0
- package/dist/bridge/approval-actions.d.ts +1 -1
- package/dist/bridge/approval-actions.js +1 -1
- package/dist/bridge/bash-run.d.ts +71 -0
- package/dist/bridge/bash-run.js +217 -0
- package/dist/bridge/compact.d.ts +155 -0
- package/dist/bridge/compact.js +450 -0
- package/dist/bridge/final-usage.js +4 -4
- package/dist/bridge/inbound-media.js +1 -1
- package/dist/bridge/index.d.ts +120 -119
- package/dist/bridge/index.js +257 -695
- package/dist/bridge/job-watch.d.ts +68 -0
- package/dist/bridge/job-watch.js +146 -0
- package/dist/bridge/queue-manager.d.ts +3 -3
- package/dist/bridge/queue-manager.js +10 -29
- package/dist/card/approval-render.d.ts +2 -2
- package/dist/card/approval-render.js +109 -97
- package/dist/card/bash-card-session.js +2 -0
- package/dist/card/card-budget.js +1 -1
- package/dist/card/card-helpers.d.ts +3 -3
- package/dist/card/card-helpers.js +6 -6
- package/dist/card/card-session.d.ts +17 -0
- package/dist/card/card-session.js +35 -0
- package/dist/card/final-answer-file.js +1 -1
- package/dist/card/run-card-session.js +2 -0
- package/dist/card/run-renderer.d.ts +3 -3
- package/dist/card/run-renderer.js +77 -102
- package/dist/card/run-state.d.ts +35 -8
- package/dist/card/run-state.js +117 -90
- package/dist/card/tool-render.d.ts +1 -1
- package/dist/card/tool-render.js +1 -1
- package/dist/card/usage-format.d.ts +12 -0
- package/dist/card/usage-format.js +8 -3
- package/dist/cli.js +15 -3
- package/dist/clone.js +2 -2
- package/dist/config/codex-config.js +130 -106
- package/dist/config/index.d.ts +16 -2
- package/dist/config/index.js +23 -8
- package/dist/connector/index.js +6 -6
- package/dist/error-classification.js +3 -2
- package/dist/inbound/placeholder.d.ts +1 -1
- package/dist/inbound/placeholder.js +1 -1
- package/dist/index.js +203 -133
- package/dist/logger/index.js +6 -6
- package/dist/message-handlers.d.ts +0 -5
- package/dist/message-handlers.js +4 -2
- package/dist/model-catalog.d.ts +2 -2
- package/dist/model-catalog.js +3 -8
- package/dist/platform/identity.js +1 -1
- package/dist/platform/path.d.ts +1 -1
- package/dist/platform/path.js +1 -1
- package/dist/platform/sleep-blocker.js +1 -1
- package/dist/platform/terminator-win32.js +2 -1
- package/dist/router/commands/resume.js +2 -20
- package/dist/router/config/dsh.d.ts +4 -8
- package/dist/router/config/dsh.js +3 -10
- package/dist/router/config/kimi.js +1 -1
- package/dist/router/config/types.d.ts +1 -1
- package/dist/router/config-diff.js +1 -1
- package/dist/router/index.d.ts +56 -11
- package/dist/router/index.js +222 -202
- package/dist/runner/claude/session.d.ts +1 -1
- package/dist/runner/claude/session.js +6 -4
- package/dist/runner/codex/app-server/runner.d.ts +9 -2
- package/dist/runner/codex/app-server/runner.js +30 -25
- package/dist/runner/codex/app-server/translator.d.ts +0 -5
- package/dist/runner/codex/app-server/translator.js +4 -17
- package/dist/runner/common/acp/acp-approval.d.ts +1 -1
- package/dist/runner/common/acp/acp-approval.js +1 -1
- package/dist/runner/common/acp/base-acp-runner.d.ts +5 -2
- package/dist/runner/common/acp/base-acp-runner.js +26 -65
- package/dist/runner/common/acp/base-translator.d.ts +12 -2
- package/dist/runner/common/acp/base-translator.js +31 -9
- package/dist/runner/common/acp/protocol-types.d.ts +1 -1
- package/dist/runner/common/acp/protocol-types.js +2 -2
- package/dist/runner/common/connection-based-runner.d.ts +32 -1
- package/dist/runner/common/connection-based-runner.js +32 -2
- package/dist/runner/common/jsonrpc/connection-manager.d.ts +2 -2
- package/dist/runner/common/jsonrpc/connection-manager.js +4 -4
- package/dist/runner/common/spawning-runner.d.ts +1 -1
- package/dist/runner/common/spawning-runner.js +1 -1
- package/dist/runner/dsh/catalog-probe.d.ts +17 -0
- package/dist/runner/dsh/catalog-probe.js +10 -0
- package/dist/runner/dsh/client.d.ts +13 -8
- package/dist/runner/dsh/client.js +23 -15
- package/dist/runner/dsh/exit-cancel.d.ts +2 -2
- package/dist/runner/dsh/exit-cancel.js +2 -2
- package/dist/runner/dsh/inflight.d.ts +1 -1
- package/dist/runner/dsh/inflight.js +1 -1
- package/dist/runner/dsh/runner.d.ts +48 -2
- package/dist/runner/dsh/runner.js +288 -199
- package/dist/runner/dsh/translator.d.ts +1 -1
- package/dist/runner/dsh/translator.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/kimi/acp/runner.d.ts +1 -2
- package/dist/runner/kimi/acp/runner.js +1 -2
- package/dist/runner/kimi/acp/translator.d.ts +1 -1
- package/dist/runner/kimi/acp/translator.js +3 -4
- package/dist/runner/opencode/acp/runner.d.ts +2 -2
- package/dist/runner/opencode/acp/runner.js +4 -4
- package/dist/runner/pi/rpc/protocol-types.d.ts +1 -1
- package/dist/runner/pi/rpc/protocol-types.js +1 -1
- package/dist/runner/pi/rpc/runner.d.ts +3 -0
- package/dist/runner/pi/rpc/runner.js +27 -42
- package/dist/runner/types.d.ts +25 -8
- package/dist/runner/types.js +1 -1
- package/dist/session/claude/sessions.d.ts +45 -0
- package/dist/session/claude/sessions.js +97 -71
- package/dist/session/codex/rollout-reader.js +4 -4
- package/dist/session/common/throw-session-list-error.d.ts +10 -0
- package/dist/session/common/throw-session-list-error.js +16 -0
- package/dist/session/dsh/sessions.js +11 -5
- package/dist/session/kimi/sessions.d.ts +40 -1
- package/dist/session/kimi/sessions.js +244 -192
- package/dist/session/opencode/sessions.d.ts +153 -1
- package/dist/session/opencode/sessions.js +354 -321
- package/dist/session/pi/sessions.js +4 -5
- package/dist/session/session-store.d.ts +1 -1
- package/dist/session/session-store.js +1 -1
- package/dist/update/version-check.js +2 -1
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.js +1 -1
- package/package.json +1 -1
|
@@ -392,6 +392,123 @@ function extractCustomProvider(providers) {
|
|
|
392
392
|
const keys = Object.keys(providers);
|
|
393
393
|
return keys.find((k) => k !== 'openai' && k !== 'anthropic');
|
|
394
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* 管线第 1 段(IO):读 + 解析 config.toml,不做任何语义解释。
|
|
397
|
+
* - missing:文件不存在;
|
|
398
|
+
* - parsed:TOML 解析成功(内容后续由 normalizeProviders 解释);
|
|
399
|
+
* - invalid:读取/解析抛错(含 TOCTOU 窗口内的文件损坏)——错误在此分类收口,
|
|
400
|
+
* 消费方(loadCodexConfig)据此走「解析失败」兜底,绝不向上抛异常。
|
|
401
|
+
*/
|
|
402
|
+
function readCodexToml(codexHome) {
|
|
403
|
+
const configFile = path.join(codexHome, 'config.toml');
|
|
404
|
+
if (!fs.existsSync(configFile))
|
|
405
|
+
return { state: 'missing' };
|
|
406
|
+
try {
|
|
407
|
+
const raw = fs.readFileSync(configFile, 'utf-8');
|
|
408
|
+
return { state: 'parsed', parsed: TOML.parse(raw) };
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
return { state: 'invalid' };
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* 管线第 2 段(纯转换):把已解析的 TOML + 目录上下文归一成 provider/model 事实。
|
|
416
|
+
* Model filtering strategy:
|
|
417
|
+
* - Custom provider: model from config.toml (single model)
|
|
418
|
+
* - openai: all bundled models
|
|
419
|
+
* - anthropic: bundled models with 'claude-*' prefix
|
|
420
|
+
*/
|
|
421
|
+
function normalizeProviders(parsed, ctx) {
|
|
422
|
+
const { catalogMode, catalogSlugs, allModels, anthropicModels } = ctx;
|
|
423
|
+
const modelKeyRaw = typeof parsed.model === 'string' && parsed.model.length > 0 ? parsed.model : undefined;
|
|
424
|
+
const currentProvider = String(parsed.model_provider ?? FALLBACK_PROVIDERS[0]);
|
|
425
|
+
// Extract model_providers section
|
|
426
|
+
const modelProviders = (parsed.model_providers ?? {});
|
|
427
|
+
const rawProviderNames = Object.keys(modelProviders);
|
|
428
|
+
if (catalogMode) {
|
|
429
|
+
// catalog 模式:provider 列表 = 内置 openai + [model_providers.*](对齐 codex
|
|
430
|
+
// merge_configured_model_providers(built_in_model_providers, cfg.model_providers),
|
|
431
|
+
// core/src/config/mod.rs:3655;model_provider 未声明时默认 "openai",mod.rs:3659)。
|
|
432
|
+
// anthropic 不是 codex 内置 provider,未显式配置时不得出现。模型列表仍只来自
|
|
433
|
+
// 活动目录——openai+内置 gpt-5.x 的失效路径不因 provider 合并复活。
|
|
434
|
+
const providerNames = rawProviderNames.includes('openai')
|
|
435
|
+
? rawProviderNames
|
|
436
|
+
: ['openai', ...rawProviderNames];
|
|
437
|
+
const providerEnvKeys = { openai: 'OPENAI_API_KEY' };
|
|
438
|
+
for (const [name, config] of Object.entries(modelProviders)) {
|
|
439
|
+
if (typeof config.env_key === 'string') {
|
|
440
|
+
providerEnvKeys[name] = config.env_key;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
// 活动目录全局:codex 运行时 provider 与模型无绑定(StaticModelsManager),
|
|
444
|
+
// 每个 provider 下拉都展示目录全部 slug
|
|
445
|
+
// 活动目录不可用(命令失败/空)时回退 [currentModel]——无目录元数据时档位/能力
|
|
446
|
+
// 不可信;禁止泄漏 FALLBACK_MODELS/内置目录。model 键缺失时不得虚构 'o3'。
|
|
447
|
+
const catalogCurrentModel = modelKeyRaw ?? catalogSlugs[0] ?? '';
|
|
448
|
+
const providerModelList = catalogSlugs.length > 0 ? catalogSlugs : modelKeyRaw ? [modelKeyRaw] : [];
|
|
449
|
+
const providerModels = {};
|
|
450
|
+
for (const name of providerNames) {
|
|
451
|
+
providerModels[name] = providerModelList;
|
|
452
|
+
}
|
|
453
|
+
const resolvedProvider = typeof parsed.model_provider === 'string' && parsed.model_provider.length > 0
|
|
454
|
+
? parsed.model_provider
|
|
455
|
+
: 'openai';
|
|
456
|
+
return {
|
|
457
|
+
currentModel: catalogCurrentModel,
|
|
458
|
+
currentProvider: resolvedProvider,
|
|
459
|
+
providerNames,
|
|
460
|
+
providerEnvKeys,
|
|
461
|
+
providerModels,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
// fallback 模式:保持原行为(openai/anthropic 内置 + bundled 模型)
|
|
465
|
+
const currentModel = modelKeyRaw ?? catalogSlugs[0] ?? 'o3';
|
|
466
|
+
const providerNames = rawProviderNames;
|
|
467
|
+
if (!providerNames.includes('openai')) {
|
|
468
|
+
providerNames.unshift('openai');
|
|
469
|
+
}
|
|
470
|
+
const customProvider = extractCustomProvider(modelProviders);
|
|
471
|
+
const providerEnvKeys = {};
|
|
472
|
+
providerEnvKeys['openai'] = 'OPENAI_API_KEY';
|
|
473
|
+
for (const [name, config] of Object.entries(modelProviders)) {
|
|
474
|
+
if (typeof config.env_key === 'string') {
|
|
475
|
+
providerEnvKeys[name] = config.env_key;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// anthropic 显式配置但未写 env_key 时保留默认键(恢复旧版无条件映射的
|
|
479
|
+
// 配置场景行为;未配置时不再虚构)
|
|
480
|
+
if (rawProviderNames.includes('anthropic') &&
|
|
481
|
+
!modelProviders['anthropic']?.env_key &&
|
|
482
|
+
providerEnvKeys['anthropic'] === undefined) {
|
|
483
|
+
providerEnvKeys['anthropic'] = 'ANTHROPIC_API_KEY';
|
|
484
|
+
}
|
|
485
|
+
const providerModels = { openai: allModels };
|
|
486
|
+
// anthropic 仅在用户显式配置时才存在(非 codex 内置 provider)
|
|
487
|
+
if (rawProviderNames.includes('anthropic')) {
|
|
488
|
+
providerModels['anthropic'] = anthropicModels;
|
|
489
|
+
}
|
|
490
|
+
if (customProvider) {
|
|
491
|
+
// Custom provider: use the model from config.toml
|
|
492
|
+
providerModels[customProvider] = [currentModel];
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
currentModel,
|
|
496
|
+
currentProvider,
|
|
497
|
+
providerNames,
|
|
498
|
+
providerEnvKeys,
|
|
499
|
+
providerModels,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* 管线第 3 段(纯装配):给 provider 事实挂上 modelOptions 查询闭包,产出
|
|
504
|
+
* 对外的 CodexConfigResult。
|
|
505
|
+
*/
|
|
506
|
+
function applyProfiles(profile) {
|
|
507
|
+
return {
|
|
508
|
+
...profile,
|
|
509
|
+
modelOptions: (provider) => buildModelOptions(profile.currentModel, profile.currentProvider, provider, profile.providerModels),
|
|
510
|
+
};
|
|
511
|
+
}
|
|
395
512
|
/**
|
|
396
513
|
* Read codex config.toml, extract provider and model info
|
|
397
514
|
*
|
|
@@ -401,8 +518,9 @@ function extractCustomProvider(providers) {
|
|
|
401
518
|
* - anthropic: bundled models with 'claude-*' prefix
|
|
402
519
|
*/
|
|
403
520
|
export function loadCodexConfig(opts = {}) {
|
|
521
|
+
// 红线:resolveCodexHome 环境变量优先级(codexHome 参数 > $CODEX_HOME > ~/.codex)
|
|
522
|
+
// 只在此解析一次,下游各段共用同一 codexHome,不得重复解析。
|
|
404
523
|
const codexHome = resolveCodexHome(opts.codexHome);
|
|
405
|
-
const configFile = path.join(codexHome, 'config.toml');
|
|
406
524
|
const catalogMode = isCodexCatalogMode(codexHome);
|
|
407
525
|
// 统一目录来源:catalog 模式 = 活动目录(model_catalog_json 整体替换内置目录);
|
|
408
526
|
// 否则 = bundled(与原行为一致)
|
|
@@ -413,111 +531,21 @@ export function loadCodexConfig(opts = {}) {
|
|
|
413
531
|
const anthropicModels = catalogSlugs.length > 0
|
|
414
532
|
? catalogSlugs.filter((m) => m.startsWith('claude-'))
|
|
415
533
|
: ANTHROPIC_FALLBACK_MODELS;
|
|
416
|
-
|
|
534
|
+
const toml = readCodexToml(codexHome);
|
|
535
|
+
if (toml.state === 'missing') {
|
|
417
536
|
// 无 config.toml:默认模型取目录首个可用模型(codex default_model_from_available),
|
|
418
537
|
// 目录不可用时回退 'o3'(FALLBACK_MODELS 首项,非 catalog 默认)
|
|
419
538
|
const currentModel = allModels[0] ?? 'o3';
|
|
420
539
|
// No config file: only openai has bundled models
|
|
421
|
-
|
|
422
|
-
openai: allModels,
|
|
423
|
-
};
|
|
424
|
-
return {
|
|
540
|
+
return applyProfiles({
|
|
425
541
|
currentModel,
|
|
426
542
|
currentProvider: FALLBACK_PROVIDERS[0],
|
|
427
543
|
providerNames: FALLBACK_PROVIDERS,
|
|
428
544
|
providerEnvKeys: { openai: 'OPENAI_API_KEY' },
|
|
429
|
-
providerModels,
|
|
430
|
-
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
try {
|
|
434
|
-
const raw = fs.readFileSync(configFile, 'utf-8');
|
|
435
|
-
const parsed = TOML.parse(raw);
|
|
436
|
-
const modelKeyRaw = typeof parsed.model === 'string' && parsed.model.length > 0 ? parsed.model : undefined;
|
|
437
|
-
const currentProvider = String(parsed.model_provider ?? FALLBACK_PROVIDERS[0]);
|
|
438
|
-
// Extract model_providers section
|
|
439
|
-
const modelProviders = (parsed.model_providers ?? {});
|
|
440
|
-
const rawProviderNames = Object.keys(modelProviders);
|
|
441
|
-
let providerNames;
|
|
442
|
-
let providerEnvKeys;
|
|
443
|
-
let providerModels;
|
|
444
|
-
if (catalogMode) {
|
|
445
|
-
// catalog 模式:provider 列表 = 内置 openai + [model_providers.*](对齐 codex
|
|
446
|
-
// merge_configured_model_providers(built_in_model_providers, cfg.model_providers),
|
|
447
|
-
// core/src/config/mod.rs:3655;model_provider 未声明时默认 "openai",mod.rs:3659)。
|
|
448
|
-
// anthropic 不是 codex 内置 provider,未显式配置时不得出现。模型列表仍只来自
|
|
449
|
-
// 活动目录——openai+内置 gpt-5.x 的失效路径不因 provider 合并复活。
|
|
450
|
-
providerNames = rawProviderNames.includes('openai')
|
|
451
|
-
? rawProviderNames
|
|
452
|
-
: ['openai', ...rawProviderNames];
|
|
453
|
-
providerEnvKeys = { openai: 'OPENAI_API_KEY' };
|
|
454
|
-
for (const [name, config] of Object.entries(modelProviders)) {
|
|
455
|
-
if (typeof config.env_key === 'string') {
|
|
456
|
-
providerEnvKeys[name] = config.env_key;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
// 活动目录全局:codex 运行时 provider 与模型无绑定(StaticModelsManager),
|
|
460
|
-
// 每个 provider 下拉都展示目录全部 slug
|
|
461
|
-
// 活动目录不可用(命令失败/空)时回退 [currentModel]——无目录元数据时档位/能力
|
|
462
|
-
// 不可信;禁止泄漏 FALLBACK_MODELS/内置目录。model 键缺失时不得虚构 'o3'。
|
|
463
|
-
const catalogCurrentModel = modelKeyRaw ?? catalogSlugs[0] ?? '';
|
|
464
|
-
const providerModelList = catalogSlugs.length > 0 ? catalogSlugs : modelKeyRaw ? [modelKeyRaw] : [];
|
|
465
|
-
providerModels = {};
|
|
466
|
-
for (const name of providerNames) {
|
|
467
|
-
providerModels[name] = providerModelList;
|
|
468
|
-
}
|
|
469
|
-
const resolvedProvider = typeof parsed.model_provider === 'string' && parsed.model_provider.length > 0
|
|
470
|
-
? parsed.model_provider
|
|
471
|
-
: 'openai';
|
|
472
|
-
return {
|
|
473
|
-
currentModel: catalogCurrentModel,
|
|
474
|
-
currentProvider: resolvedProvider,
|
|
475
|
-
providerNames,
|
|
476
|
-
providerEnvKeys,
|
|
477
|
-
providerModels,
|
|
478
|
-
modelOptions: (provider) => buildModelOptions(catalogCurrentModel, resolvedProvider, provider, providerModels),
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
// fallback 模式:保持原行为(openai/anthropic 内置 + bundled 模型)
|
|
482
|
-
const currentModel = modelKeyRaw ?? catalogSlugs[0] ?? 'o3';
|
|
483
|
-
providerNames = rawProviderNames;
|
|
484
|
-
if (!providerNames.includes('openai')) {
|
|
485
|
-
providerNames.unshift('openai');
|
|
486
|
-
}
|
|
487
|
-
const customProvider = extractCustomProvider(modelProviders);
|
|
488
|
-
providerEnvKeys = {};
|
|
489
|
-
providerEnvKeys['openai'] = 'OPENAI_API_KEY';
|
|
490
|
-
for (const [name, config] of Object.entries(modelProviders)) {
|
|
491
|
-
if (typeof config.env_key === 'string') {
|
|
492
|
-
providerEnvKeys[name] = config.env_key;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
// anthropic 显式配置但未写 env_key 时保留默认键(恢复旧版无条件映射的
|
|
496
|
-
// 配置场景行为;未配置时不再虚构)
|
|
497
|
-
if (rawProviderNames.includes('anthropic') &&
|
|
498
|
-
!modelProviders['anthropic']?.env_key &&
|
|
499
|
-
providerEnvKeys['anthropic'] === undefined) {
|
|
500
|
-
providerEnvKeys['anthropic'] = 'ANTHROPIC_API_KEY';
|
|
501
|
-
}
|
|
502
|
-
providerModels = { openai: allModels };
|
|
503
|
-
// anthropic 仅在用户显式配置时才存在(非 codex 内置 provider)
|
|
504
|
-
if (rawProviderNames.includes('anthropic')) {
|
|
505
|
-
providerModels['anthropic'] = anthropicModels;
|
|
506
|
-
}
|
|
507
|
-
if (customProvider) {
|
|
508
|
-
// Custom provider: use the model from config.toml
|
|
509
|
-
providerModels[customProvider] = [currentModel];
|
|
510
|
-
}
|
|
511
|
-
return {
|
|
512
|
-
currentModel,
|
|
513
|
-
currentProvider,
|
|
514
|
-
providerNames,
|
|
515
|
-
providerEnvKeys,
|
|
516
|
-
providerModels,
|
|
517
|
-
modelOptions: (provider) => buildModelOptions(currentModel, currentProvider, provider, providerModels),
|
|
518
|
-
};
|
|
545
|
+
providerModels: { openai: allModels },
|
|
546
|
+
});
|
|
519
547
|
}
|
|
520
|
-
|
|
548
|
+
if (toml.state === 'invalid') {
|
|
521
549
|
// config.toml 读取/解析失败:readModelCatalogJsonPath 对此返回
|
|
522
550
|
// TOML_PARSE_FAILED_SENTINEL(isCodexCatalogMode → false),因此正常路径下
|
|
523
551
|
// catalogMode 恒为 false,下面的 `if (catalogMode)` 分支只在两次读取之间
|
|
@@ -533,19 +561,15 @@ export function loadCodexConfig(opts = {}) {
|
|
|
533
561
|
modelOptions: () => [],
|
|
534
562
|
};
|
|
535
563
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
openai: allModels,
|
|
539
|
-
};
|
|
540
|
-
return {
|
|
541
|
-
currentModel,
|
|
564
|
+
return applyProfiles({
|
|
565
|
+
currentModel: catalogSlugs[0] ?? 'o3',
|
|
542
566
|
currentProvider: FALLBACK_PROVIDERS[0],
|
|
543
567
|
providerNames: FALLBACK_PROVIDERS,
|
|
544
568
|
providerEnvKeys: { openai: 'OPENAI_API_KEY' },
|
|
545
|
-
providerModels,
|
|
546
|
-
|
|
547
|
-
};
|
|
569
|
+
providerModels: { openai: allModels },
|
|
570
|
+
});
|
|
548
571
|
}
|
|
572
|
+
return applyProfiles(normalizeProviders(toml.parsed, { catalogMode, catalogSlugs, allModels, anthropicModels }));
|
|
549
573
|
}
|
|
550
574
|
/**
|
|
551
575
|
* Build model options for a provider.
|
package/dist/config/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { getConfigDir } from './dir.js';
|
|
|
4
4
|
export declare const CLAUDE_EFFORTS: readonly ["low", "medium", "high", "xhigh", "max"];
|
|
5
5
|
/**
|
|
6
6
|
* Claude 的权限模式取值:'default' 之外都是 CLI `--permission-mode` 的真实枚举
|
|
7
|
-
* (
|
|
7
|
+
* (claude --help:acceptEdits | auto | bypassPermissions | manual
|
|
8
8
|
* | dontAsk | plan)。
|
|
9
9
|
* 'default' 是本项目自造的值,不是 CLI 的取值 —— 它表示"不传 --permission-mode",
|
|
10
10
|
* 由 CLI 自己决定默认模式,转换在 runner/claude/session.ts 的 spawn 参数处。
|
|
@@ -27,7 +27,7 @@ export declare const DEFAULT_APPROVAL_TIMEOUT_MS: number;
|
|
|
27
27
|
/**
|
|
28
28
|
* 入站媒体默认配置(schema 默认与 connector 兜底共用,避免双源漂移)。
|
|
29
29
|
*
|
|
30
|
-
* 单文件上限默认 100MB:50MB 对视频偏小(
|
|
30
|
+
* 单文件上限默认 100MB:50MB 对视频偏小(mp4 会被丢弃)。
|
|
31
31
|
* 注意飞书侧 `type=file` 超过 100MB 必须用 Range 分片下载,而 SDK 的
|
|
32
32
|
* `downloadResourceToFile` 不分片(必报 234037),所以 100 是实际可用上限
|
|
33
33
|
* (inbound-message-matrix.md §4 第 4 条)。
|
|
@@ -93,6 +93,16 @@ declare const OpencodeConfigSchema: z.ZodObject<{
|
|
|
93
93
|
turnIdleTimeoutMinutes: z.ZodDefault<z.ZodNumber>;
|
|
94
94
|
}, z.core.$strip>>;
|
|
95
95
|
}, z.core.$strip>;
|
|
96
|
+
/**
|
|
97
|
+
* pi 默认配置:schema default、src/index.ts 注册兜底与 runner 构造器兜底
|
|
98
|
+
* 三处共用,避免三抄漂移。
|
|
99
|
+
*/
|
|
100
|
+
export declare const PI_DEFAULTS: {
|
|
101
|
+
readonly provider: "Volcano";
|
|
102
|
+
readonly model: "glm-5.2";
|
|
103
|
+
readonly thinking: "medium";
|
|
104
|
+
readonly tools: "read,bash,edit,write,grep,find,ls";
|
|
105
|
+
};
|
|
96
106
|
/** Pi-specific configuration. pi is a spawn-per-message CLI like Claude. */
|
|
97
107
|
declare const PiConfigSchema: z.ZodObject<{
|
|
98
108
|
provider: z.ZodDefault<z.ZodString>;
|
|
@@ -107,6 +117,10 @@ declare const PiConfigSchema: z.ZodObject<{
|
|
|
107
117
|
}>>;
|
|
108
118
|
tools: z.ZodDefault<z.ZodString>;
|
|
109
119
|
}, z.core.$strip>;
|
|
120
|
+
/** kimi 默认模型:schema default 与 src/index.ts 注册兜底共用,避免双抄漂移。 */
|
|
121
|
+
export declare const KIMI_DEFAULTS: {
|
|
122
|
+
readonly model: "kimi-code/k3";
|
|
123
|
+
};
|
|
110
124
|
/** Kimi-specific configuration. Pure ACP mode (persistent `kimi acp` connection). */
|
|
111
125
|
declare const KimiConfigSchema: z.ZodObject<{
|
|
112
126
|
model: z.ZodDefault<z.ZodString>;
|
package/dist/config/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import YAML from 'yaml';
|
|
5
5
|
import { getLogger } from '../logger/index.js';
|
|
6
6
|
import { atomicWrite } from '../persistence/atomic-write.js';
|
|
7
|
+
import { AGENT_KINDS } from '../agent-kinds.js';
|
|
7
8
|
export { getConfigDir } from './dir.js';
|
|
8
9
|
// Import constants from agent config files (SSOT: Layer 1 source)
|
|
9
10
|
import { KIMI_THINKING_EFFORTS } from './kimi-config.js';
|
|
@@ -11,7 +12,7 @@ import { KIMI_THINKING_EFFORTS } from './kimi-config.js';
|
|
|
11
12
|
export const CLAUDE_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
12
13
|
/**
|
|
13
14
|
* Claude 的权限模式取值:'default' 之外都是 CLI `--permission-mode` 的真实枚举
|
|
14
|
-
* (
|
|
15
|
+
* (claude --help:acceptEdits | auto | bypassPermissions | manual
|
|
15
16
|
* | dontAsk | plan)。
|
|
16
17
|
* 'default' 是本项目自造的值,不是 CLI 的取值 —— 它表示"不传 --permission-mode",
|
|
17
18
|
* 由 CLI 自己决定默认模式,转换在 runner/claude/session.ts 的 spawn 参数处。
|
|
@@ -55,7 +56,7 @@ export const DEFAULT_APPROVAL_TIMEOUT_MS = DEFAULTS.APPROVAL_TIMEOUT_MS;
|
|
|
55
56
|
/**
|
|
56
57
|
* 入站媒体默认配置(schema 默认与 connector 兜底共用,避免双源漂移)。
|
|
57
58
|
*
|
|
58
|
-
* 单文件上限默认 100MB:50MB 对视频偏小(
|
|
59
|
+
* 单文件上限默认 100MB:50MB 对视频偏小(mp4 会被丢弃)。
|
|
59
60
|
* 注意飞书侧 `type=file` 超过 100MB 必须用 Range 分片下载,而 SDK 的
|
|
60
61
|
* `downloadResourceToFile` 不分片(必报 234037),所以 100 是实际可用上限
|
|
61
62
|
* (inbound-message-matrix.md §4 第 4 条)。
|
|
@@ -141,21 +142,35 @@ const OpencodeConfigSchema = z.object({
|
|
|
141
142
|
})
|
|
142
143
|
.optional(),
|
|
143
144
|
});
|
|
145
|
+
/**
|
|
146
|
+
* pi 默认配置:schema default、src/index.ts 注册兜底与 runner 构造器兜底
|
|
147
|
+
* 三处共用,避免三抄漂移。
|
|
148
|
+
*/
|
|
149
|
+
export const PI_DEFAULTS = {
|
|
150
|
+
provider: 'Volcano',
|
|
151
|
+
model: 'glm-5.2',
|
|
152
|
+
thinking: 'medium',
|
|
153
|
+
tools: 'read,bash,edit,write,grep,find,ls',
|
|
154
|
+
};
|
|
144
155
|
/** Pi-specific configuration. pi is a spawn-per-message CLI like Claude. */
|
|
145
156
|
const PiConfigSchema = z.object({
|
|
146
157
|
/** LLM provider, e.g. 'Volcano', 'anthropic', 'openai'. */
|
|
147
|
-
provider: z.string().default(
|
|
158
|
+
provider: z.string().default(PI_DEFAULTS.provider),
|
|
148
159
|
/** Model ID or alias, e.g. 'glm-5.2'. */
|
|
149
|
-
model: z.string().default(
|
|
160
|
+
model: z.string().default(PI_DEFAULTS.model),
|
|
150
161
|
/** Thinking level: off/minimal/low/medium/high/xhigh. */
|
|
151
|
-
thinking: z.enum(PI_THINKING_LEVELS).default(
|
|
162
|
+
thinking: z.enum(PI_THINKING_LEVELS).default(PI_DEFAULTS.thinking),
|
|
152
163
|
/** Comma-separated tool whitelist. */
|
|
153
|
-
tools: z.string().default(
|
|
164
|
+
tools: z.string().default(PI_DEFAULTS.tools),
|
|
154
165
|
});
|
|
166
|
+
/** kimi 默认模型:schema default 与 src/index.ts 注册兜底共用,避免双抄漂移。 */
|
|
167
|
+
export const KIMI_DEFAULTS = {
|
|
168
|
+
model: 'kimi-code/k3',
|
|
169
|
+
};
|
|
155
170
|
/** Kimi-specific configuration. Pure ACP mode (persistent `kimi acp` connection). */
|
|
156
171
|
const KimiConfigSchema = z.object({
|
|
157
172
|
/** Model ID or alias, e.g. 'kimi-code/k3'. */
|
|
158
|
-
model: z.string().default(
|
|
173
|
+
model: z.string().default(KIMI_DEFAULTS.model),
|
|
159
174
|
/** Thinking effort,取值见 KIMI_THINKING_EFFORTS('low' | 'high' | 'max')。 */
|
|
160
175
|
thinkingEffort: z.enum(KIMI_THINKING_EFFORTS).default('max'),
|
|
161
176
|
/** Permission mode: 'manual' (approve each), 'auto' (engine decides), 'yolo' (allow all). */
|
|
@@ -307,7 +322,7 @@ export const AppConfigSchema = z.object({
|
|
|
307
322
|
/** 入站媒体(图片/文件)落盘配置。 */
|
|
308
323
|
inboundMedia: InboundMediaConfigSchema.default(InboundMediaConfigSchema.parse({})),
|
|
309
324
|
/** Default agent for new runs. */
|
|
310
|
-
defaultAgent: z.enum(
|
|
325
|
+
defaultAgent: z.enum(AGENT_KINDS).default('claude'),
|
|
311
326
|
/** Check for updates on lark-remote startup (default: false). */
|
|
312
327
|
checkUpdateOnStartup: z.boolean().default(false),
|
|
313
328
|
});
|
package/dist/connector/index.js
CHANGED
|
@@ -204,8 +204,8 @@ function isAccessTokenRejected(err) {
|
|
|
204
204
|
* CardStreamController 经 throttle 延迟触发 —— `controller.update()` 调完
|
|
205
205
|
* `throttle.note()` 就 resolve,不等真正的 patch。失败时是一条脱离 await 链的
|
|
206
206
|
* detached rejection,只能冒泡到 `process.unhandledRejection`,调用方的
|
|
207
|
-
* try/catch
|
|
208
|
-
*
|
|
207
|
+
* try/catch 根本挡不住:卡片 patch 时 socket 被关(AxiosError `ERR_SOCKET_CLOSED`),
|
|
208
|
+
* 整进程退出,正在跑的 run 陪葬。
|
|
209
209
|
*
|
|
210
210
|
* 这里在唯一的底层 patch 出口上兜住:瞬态错误重试最多 PATCH_MAX_RETRIES 次,
|
|
211
211
|
* 全部失败才把最后一个错误抛出去(此时上层 classifyRejection 也会判为
|
|
@@ -287,13 +287,13 @@ export class FeishuConnector {
|
|
|
287
287
|
},
|
|
288
288
|
});
|
|
289
289
|
// 卡片 patch 的统一出口(观测 + 重试):
|
|
290
|
-
// 1)
|
|
290
|
+
// 1) 观测:飞书业务码错误以 HTTP 200 + {code!=0}
|
|
291
291
|
// 返回时,lark SDK 正常 resolve、@larksuite/channel 的 patchCard 丢弃返回值,
|
|
292
292
|
// 导致终态卡 patch 被业务层拒绝时全链路无日志无兜底。这里把业务码记 warn。
|
|
293
293
|
// **不在这里抛**:流式卡片的 patch 由 throttle 触发、脱离 await 链
|
|
294
294
|
// (`Throttle.fireSoon` 丢掉 doFire 的 promise),抛出即成 detached rejection。
|
|
295
295
|
// 恢复链路只覆盖有 await 的调用方:见 `updateCard()` 读业务码后抛。
|
|
296
|
-
// 2)
|
|
296
|
+
// 2) 重试:瞬态传输失败就地重试,最多
|
|
297
297
|
// PATCH_MAX_RETRIES 次,不把失败直接落到 unhandledRejection 打死进程。
|
|
298
298
|
// 业务码是确定性失败,不进重试循环。
|
|
299
299
|
// Guard: unit-test mocks may omit rawClient; skip probe installation in that case.
|
|
@@ -316,7 +316,7 @@ export class FeishuConnector {
|
|
|
316
316
|
return;
|
|
317
317
|
// 判据是「是否携带可下载资源」(`msg.resources`),不是 `msg_type` 白名单:
|
|
318
318
|
// SDK 只为 image/file/audio/video/media/sticker 五类产出非空 resources,
|
|
319
|
-
// 枚举 msg_type 必然漏(
|
|
319
|
+
// 枚举 msg_type 必然漏(mp4 被当文本转发给 agent)。
|
|
320
320
|
// 一条消息可以**同时**产出资源事件与文本事件(post 既有文字又有图),
|
|
321
321
|
// 由的装配器合并成同一个 turn。
|
|
322
322
|
const hasResources = msg.resources.length > 0;
|
|
@@ -398,7 +398,7 @@ export class FeishuConnector {
|
|
|
398
398
|
});
|
|
399
399
|
}
|
|
400
400
|
catch (err) {
|
|
401
|
-
getLogger().error('[feishu] inbound media detected handler failed:', err
|
|
401
|
+
getLogger().error('[feishu] inbound media detected handler failed:', err);
|
|
402
402
|
}
|
|
403
403
|
}
|
|
404
404
|
/**
|
|
@@ -44,8 +44,9 @@ export function classifyRejection(reason) {
|
|
|
44
44
|
if (status !== undefined && status >= 500 && status < 600)
|
|
45
45
|
return 'recoverable';
|
|
46
46
|
// 传输层瞬态失败:连接/socket 级别,与进程状态无关。
|
|
47
|
-
//
|
|
48
|
-
//
|
|
47
|
+
// 这条必须先于业务码判定:AxiosError `ERR_SOCKET_CLOSED`(卡片 patch 时
|
|
48
|
+
// socket 被关)没有 HTTP status,漏判会落到 fatal → process.exit(1),
|
|
49
|
+
// 正在跑的 agent run 陪葬。
|
|
49
50
|
if (isTransientTransportError(reason))
|
|
50
51
|
return 'recoverable';
|
|
51
52
|
// 飞书 API 业务错误(如 230027 外部会话无权限)—— 经 SDK throttle detach 路径逃逸的
|