c0de-agent 1.3.0 → 1.4.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/dist/cli/deps.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { decryptSecret } from '../core/secret.js';
2
- import { createRegistry, registerProvider } from '../llm/index.js';
2
+ import { createRegistry, overrideToCapabilities, registerProvider } from '../llm/index.js';
3
3
  import { initPlugins } from '../plugins/index.js';
4
4
  import { createDefaultRegistry, createDefaultURLRegistry } from '../tools/index.js';
5
5
  import { autoAllowChecker } from '../tools/permission.js';
@@ -34,6 +34,9 @@ function registerProviderFromConfig(registry, p) {
34
34
  baseURL: p.baseURL,
35
35
  apiKey: p.apiKey ? decryptSecret(p.apiKey) : p.apiKey,
36
36
  ...(path ? { path } : {}),
37
+ // 传递用户配置的 per-model capabilities(contextWindow 等),
38
+ // 否则 resolveRoute 回退到 DEFAULT_MODEL_CAPABILITIES,可能导致预算过小。
39
+ ...(p.models ? { models: overrideToCapabilities(p.models) } : {}),
37
40
  });
38
41
  }
39
42
  /** 解析权限 checker:显式策略优先,否则回退到 config.permission.defaultMode。 */
@@ -3,7 +3,9 @@ import { getLLMSegments } from '../session/session.js';
3
3
  import { generateId } from '../shared/index.js';
4
4
  import { listTools } from '../tools/registry.js';
5
5
  import { estimateBudget } from './context.js';
6
+ import { createTokenBudget } from './context.js';
6
7
  import { agentLoop } from './loop.js';
8
+ import { resolveRoute } from '../llm/registry.js';
7
9
  import { DEFAULT_SESSION_TITLE, generateSessionTitle } from './title.js';
8
10
  async function createAgent(session, config, deps) {
9
11
  const messages = await getMessages(deps.db, session.id);
@@ -13,6 +15,18 @@ async function createAgent(session, config, deps) {
13
15
  const segments = await getLLMSegments(deps.db, session.id);
14
16
  const allTools = listTools(deps.toolRegistry, { config: {}, cwd: deps.cwd });
15
17
  const tools = allTools.filter((t) => config.tools.includes(t.name));
18
+ // 从 registry 解析模型的 contextWindow,使初始 token 预算与真实窗口一致;
19
+ // 解析失败(provider 未注册 / 模型未知)回退到保守的 128k,首轮流式时
20
+ // resolveEffectiveContextWindow 会再纠正。
21
+ let contextWindow = 128_000;
22
+ try {
23
+ const { capabilities } = resolveRoute(deps.llmRegistry, config.provider, config.model);
24
+ contextWindow = capabilities.contextWindow;
25
+ }
26
+ catch {
27
+ // provider 未注册或模型未知:保留回退值,loop 首轮会同步
28
+ }
29
+ const tokenBudget = createTokenBudget(contextWindow);
16
30
  return {
17
31
  id: generateId(),
18
32
  session,
@@ -23,14 +37,7 @@ async function createAgent(session, config, deps) {
23
37
  abortController: new AbortController(),
24
38
  steeringQueue: [],
25
39
  segments,
26
- tokenBudget: {
27
- total: 128_000,
28
- reserved: 25_600,
29
- available: 102_400,
30
- historyBudget: 76_800,
31
- used,
32
- keepRecent: 12_800,
33
- },
40
+ tokenBudget: { ...tokenBudget, used },
34
41
  calibrationFactor: 1.0,
35
42
  // 压缩模型覆盖:从全局配置映射到 agent state,compactContext 读取后用于
36
43
  // 创建 summarizer。未配置时为 undefined → 回退到会话主模型。
@@ -4,7 +4,7 @@ export type { ChatOptions, ProviderContext } from './provider.js';
4
4
  export { buildInternalRequest, chat, chatStream, toInternalMessage, toStreamChunk, } from './provider.js';
5
5
  export { isContextOverflow, isContextOverflowFailure } from './provider-error.js';
6
6
  export type { ProviderInput, Registry, ResolveResult } from './registry.js';
7
- export { builtinCapabilities, createRegistry, registerProvider, resolveModelByRole, resolveRoute, setRole, } from './registry.js';
7
+ export { builtinCapabilities, createRegistry, DEFAULT_MODEL_CAPABILITIES, overrideToCapabilities, registerProvider, resolveModelByRole, resolveRoute, setRole, } from './registry.js';
8
8
  export type { Retryable, RetryOptions } from './retry.js';
9
9
  export { delay, retryable, withRetry } from './retry.js';
10
10
  export type { FallbackChain } from './routing.js';
package/dist/llm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { openAICompatRoute } from './protocols/openai-compat.js';
2
2
  export { buildInternalRequest, chat, chatStream, toInternalMessage, toStreamChunk, } from './provider.js';
3
3
  export { isContextOverflow, isContextOverflowFailure } from './provider-error.js';
4
- export { builtinCapabilities, createRegistry, registerProvider, resolveModelByRole, resolveRoute, setRole, } from './registry.js';
4
+ export { builtinCapabilities, createRegistry, DEFAULT_MODEL_CAPABILITIES, overrideToCapabilities, registerProvider, resolveModelByRole, resolveRoute, setRole, } from './registry.js';
5
5
  export { delay, retryable, withRetry } from './retry.js';
6
6
  export { runWithFallback, shouldFallOver } from './routing.js';
7
7
  export * from './schema/index.js';
@@ -1,4 +1,4 @@
1
- import type { ModelCapabilities, ModelRole } from '../shared/types/llm.js';
1
+ import type { ModelCapabilities, ModelOverride, ModelRole } from '../shared/types/llm.js';
2
2
  import { openAICompatRoute } from './protocols/openai-compat.js';
3
3
  import type { Model } from './schema/options.js';
4
4
  type RouteEntry = ReturnType<typeof openAICompatRoute> & {
@@ -26,6 +26,22 @@ type ResolveResult = {
26
26
  model: Model;
27
27
  capabilities: ModelCapabilities;
28
28
  };
29
+ /**
30
+ * Default capabilities for models not explicitly declared in the route's models map.
31
+ *
32
+ * Modern models overwhelmingly support ≥128k context windows; the previous 8192
33
+ * default caused false-positive compaction deadlocks on any provider that
34
+ * didn't declare per-model capabilities. 128k is a conservative floor that
35
+ * matches the most common modern context window.
36
+ */
37
+ declare const DEFAULT_MODEL_CAPABILITIES: ModelCapabilities;
38
+ /**
39
+ * Merge sparse per-model overrides from config (ModelOverride) into full
40
+ * ModelCapabilities by filling gaps with DEFAULT_MODEL_CAPABILITIES.
41
+ * Strips `enabled` (a UI-only concern) — the registry tracks all models
42
+ * regardless of selector visibility.
43
+ */
44
+ declare function overrideToCapabilities(overrides: Record<string, ModelOverride>): Record<string, ModelCapabilities>;
29
45
  /**
30
46
  * Resolve a (provider, modelId) pair into a route + typed model.
31
47
  * Throws NoRoute when the provider is unknown.
@@ -41,4 +57,4 @@ declare const setRole: (registry: Registry, role: ModelRole, provider: string, m
41
57
  /** Default role + a starter catalog of well-known models. */
42
58
  declare const builtinCapabilities: Record<string, Record<string, ModelCapabilities>>;
43
59
  export type { ProviderInput, Registry, ResolveResult, RouteEntry };
44
- export { builtinCapabilities, createRegistry, registerProvider, resolveModelByRole, resolveRoute, setRole, };
60
+ export { builtinCapabilities, createRegistry, DEFAULT_MODEL_CAPABILITIES, overrideToCapabilities, registerProvider, resolveModelByRole, resolveRoute, setRole, };
@@ -15,6 +15,44 @@ const registerProvider = (registry, input) => {
15
15
  models: input.models ?? {},
16
16
  });
17
17
  };
18
+ /**
19
+ * Default capabilities for models not explicitly declared in the route's models map.
20
+ *
21
+ * Modern models overwhelmingly support ≥128k context windows; the previous 8192
22
+ * default caused false-positive compaction deadlocks on any provider that
23
+ * didn't declare per-model capabilities. 128k is a conservative floor that
24
+ * matches the most common modern context window.
25
+ */
26
+ const DEFAULT_MODEL_CAPABILITIES = {
27
+ contextWindow: 128_000,
28
+ maxOutput: 8192,
29
+ supportsTools: true,
30
+ supportsVision: false,
31
+ supportsThinking: false,
32
+ costPer1kInput: 0,
33
+ costPer1kOutput: 0,
34
+ };
35
+ /**
36
+ * Merge sparse per-model overrides from config (ModelOverride) into full
37
+ * ModelCapabilities by filling gaps with DEFAULT_MODEL_CAPABILITIES.
38
+ * Strips `enabled` (a UI-only concern) — the registry tracks all models
39
+ * regardless of selector visibility.
40
+ */
41
+ function overrideToCapabilities(overrides) {
42
+ const result = {};
43
+ for (const [name, o] of Object.entries(overrides)) {
44
+ result[name] = {
45
+ contextWindow: o.contextWindow ?? DEFAULT_MODEL_CAPABILITIES.contextWindow,
46
+ maxOutput: o.maxOutput ?? DEFAULT_MODEL_CAPABILITIES.maxOutput,
47
+ supportsTools: o.supportsTools ?? DEFAULT_MODEL_CAPABILITIES.supportsTools,
48
+ supportsVision: o.supportsVision ?? DEFAULT_MODEL_CAPABILITIES.supportsVision,
49
+ supportsThinking: o.supportsThinking ?? DEFAULT_MODEL_CAPABILITIES.supportsThinking,
50
+ costPer1kInput: o.costPer1kInput ?? DEFAULT_MODEL_CAPABILITIES.costPer1kInput,
51
+ costPer1kOutput: o.costPer1kOutput ?? DEFAULT_MODEL_CAPABILITIES.costPer1kOutput,
52
+ };
53
+ }
54
+ return result;
55
+ }
18
56
  /**
19
57
  * Resolve a (provider, modelId) pair into a route + typed model.
20
58
  * Throws NoRoute when the provider is unknown.
@@ -29,16 +67,7 @@ const resolveRoute = (registry, provider, modelId) => {
29
67
  model: modelId,
30
68
  });
31
69
  }
32
- const capabilities = route.models[modelId] ??
33
- {
34
- contextWindow: 8192,
35
- maxOutput: 4096,
36
- supportsTools: true,
37
- supportsVision: false,
38
- supportsThinking: false,
39
- costPer1kInput: 0,
40
- costPer1kOutput: 0,
41
- };
70
+ const capabilities = route.models[modelId] ?? DEFAULT_MODEL_CAPABILITIES;
42
71
  return {
43
72
  route,
44
73
  model: makeModel(modelId, provider, {
@@ -104,4 +133,4 @@ const builtinCapabilities = {
104
133
  },
105
134
  },
106
135
  };
107
- export { builtinCapabilities, createRegistry, registerProvider, resolveModelByRole, resolveRoute, setRole, };
136
+ export { builtinCapabilities, createRegistry, DEFAULT_MODEL_CAPABILITIES, overrideToCapabilities, registerProvider, resolveModelByRole, resolveRoute, setRole, };
@@ -9,7 +9,7 @@ import { loadConfig } from '../core/config.js';
9
9
  import { decryptSecret } from '../core/secret.js';
10
10
  import { BUILTIN_WORKFLOWS, createWorkflowRegistry } from '../core/workflows/index.js';
11
11
  import { createDB, migrateDB } from '../db/index.js';
12
- import { createRegistry, registerProvider } from '../llm/registry.js';
12
+ import { createRegistry, overrideToCapabilities, registerProvider, } from '../llm/registry.js';
13
13
  import { initPlugins } from '../plugins/index.js';
14
14
  import { createDefaultRegistry, createDefaultURLRegistry } from '../tools/index.js';
15
15
  import { checkForUpdate, createHandoffServer, createUpdateScheduler, requestHandoff, restoreSessions, } from '../update/index.js';
@@ -37,6 +37,9 @@ function registerProviderFromConfig(registry, p) {
37
37
  baseURL: p.baseURL,
38
38
  apiKey: p.apiKey ? decryptSecret(p.apiKey) : p.apiKey,
39
39
  ...(path ? { path } : {}),
40
+ // 传递用户配置的 per-model capabilities(contextWindow 等),
41
+ // 否则 resolveRoute 回退到 DEFAULT_MODEL_CAPABILITIES,可能导致预算过小。
42
+ ...(p.models ? { models: overrideToCapabilities(p.models) } : {}),
40
43
  });
41
44
  }
42
45
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c0de-agent",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Open-source AI coding assistant with Browser-Server architecture",
5
5
  "type": "module",
6
6
  "bin": {