neoctl 0.2.58 → 0.2.60

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.
Files changed (37) hide show
  1. package/dist/core/context-token-calibration.d.ts +10 -0
  2. package/dist/core/context-token-calibration.js +45 -0
  3. package/dist/core/context-token-calibration.js.map +1 -0
  4. package/dist/core/query-engine.d.ts +1 -0
  5. package/dist/core/query-engine.js +15 -3
  6. package/dist/core/query-engine.js.map +1 -1
  7. package/dist/core/query.d.ts +2 -0
  8. package/dist/core/query.js +23 -4
  9. package/dist/core/query.js.map +1 -1
  10. package/dist/model/agent-settings-boundary.js +7 -9
  11. package/dist/model/agent-settings-boundary.js.map +1 -1
  12. package/dist/model/anthropic-adapter.d.ts +5 -0
  13. package/dist/model/anthropic-adapter.js +69 -0
  14. package/dist/model/anthropic-adapter.js.map +1 -1
  15. package/dist/model/communication-logger.d.ts +2 -0
  16. package/dist/model/communication-logger.js +2 -0
  17. package/dist/model/communication-logger.js.map +1 -1
  18. package/dist/model/composition-runtime.d.ts +11 -0
  19. package/dist/model/composition-runtime.js +39 -1
  20. package/dist/model/composition-runtime.js.map +1 -1
  21. package/dist/model/model-gateway.d.ts +2 -0
  22. package/dist/model/model-gateway.js.map +1 -1
  23. package/dist/model/settings-store.d.ts +24 -4
  24. package/dist/model/settings-store.js +137 -10
  25. package/dist/model/settings-store.js.map +1 -1
  26. package/dist/model/settings-sync.d.ts +2 -1
  27. package/dist/model/settings-sync.js +4 -2
  28. package/dist/model/settings-sync.js.map +1 -1
  29. package/dist/repl/index.js +8 -7
  30. package/dist/repl/index.js.map +1 -1
  31. package/dist/types/events.d.ts +2 -0
  32. package/dist/web/html.js +1 -1
  33. package/dist/web/index.js +29 -11
  34. package/dist/web/index.js.map +1 -1
  35. package/dist/web/model-settings-api.js +4 -3
  36. package/dist/web/model-settings-api.js.map +1 -1
  37. package/package.json +1 -1
@@ -30,6 +30,8 @@ export interface PromptCacheDiagnostics {
30
30
  export interface ContextMetrics {
31
31
  model?: string;
32
32
  estimatedInputTokens: number;
33
+ /** Prefer this unified estimate/count over generation usage for context display. */
34
+ inputTokenSource?: "estimate";
33
35
  estimatedChars: number;
34
36
  messageCount: number;
35
37
  toolCount: number;
package/dist/web/html.js CHANGED
@@ -405,7 +405,7 @@ function renderStatus() {
405
405
  const displayPhase = minimumDisplayPhase(s.phase || 'ready');
406
406
  const phase = phaseLabel(displayPhase);
407
407
  const ctx = contextParts(s.metrics);
408
- const inputTokens = compactNumber(animatedNumber('input', (s.usage && s.usage.inputTokens) ?? (s.metrics && s.metrics.estimatedInputTokens)));
408
+ const inputTokens = compactNumber(animatedNumber('input', s.metrics?.inputTokenSource ? s.metrics.estimatedInputTokens : (s.usage && s.usage.inputTokens) ?? (s.metrics && s.metrics.estimatedInputTokens)));
409
409
  const outputTokens = compactNumber(animatedNumber('output', (s.usage && s.usage.outputTokens) ?? s.streamedOutputTokens));
410
410
  const model = truncateMiddle((s.metrics && s.metrics.model) || 'model?', window.innerWidth > 900 ? 26 : 14);
411
411
  const phaseActive = isActivePhase(displayPhase);
package/dist/web/index.js CHANGED
@@ -3,8 +3,8 @@ import { trackSettingsGateway } from "../model/settings-sync.js";
3
3
  import { observeModelSettings } from "../model/settings-sync.js";
4
4
  import { modelProtocols } from "../model/context-window.js";
5
5
  import { isReasoningEffort } from "../model/model-gateway.js";
6
- import { ModelSettingsStore, compositionModelConfig } from "../model/settings-store.js";
7
- import { registerCompositionTools } from "../model/composition-runtime.js";
6
+ import { ModelSettingsStore, routeModel } from "../model/settings-store.js";
7
+ import { registerCompositionTools, createCompositionGateway } from "../model/composition-runtime.js";
8
8
  import { handleModelSettingsRequest } from "./model-settings-api.js";
9
9
  import { paginateSessions, sessionPageOptions } from "../session/session-pagination.js";
10
10
  import { applyToolInputChanges } from "../model/tool-input-stream.js";
@@ -158,9 +158,10 @@ export async function createWebRuntime(options = {}) {
158
158
  const settingsStore = new ModelSettingsStore();
159
159
  const appliedSettings = settingsStore.read()?.applied;
160
160
  const settingsRevisions = new WeakMap();
161
- const modelConfig = appliedSettings ? compositionModelConfig(appliedSettings.composition, appliedSettings.connections) : readModelProviderConfig(process.env);
161
+ const appliedGateway = appliedSettings ? createCompositionGateway(appliedSettings.composition, appliedSettings.connections) : undefined;
162
+ const modelConfig = appliedGateway ? appliedGateway.config : readModelProviderConfig(process.env);
162
163
  const communicationLogger = new CommunicationLogger();
163
- const modelGateway = trackSettingsGateway(new LoggingModelGateway(createModelGatewayFromConfig(modelConfig), communicationLogger), appliedSettings?.revision, appliedSettings ? [appliedSettings.composition.main.api, appliedSettings.composition.image.api, appliedSettings.composition.search.api] : []);
164
+ const modelGateway = trackSettingsGateway(new LoggingModelGateway(appliedGateway ? appliedGateway.gateway : createModelGatewayFromConfig(modelConfig), communicationLogger), appliedSettings?.revision, appliedGateway ? appliedGateway.heldConnections : []);
164
165
  const taskStore = new TaskStore();
165
166
  const pluginCatalog = normalizeWebRuntimePlugins(options.externalPlugins);
166
167
  const pluginOverrides = normalizePluginOverrides(options.sessionPluginOverrides, pluginCatalog);
@@ -252,11 +253,12 @@ export async function createWebRuntime(options = {}) {
252
253
  const revision = applied.revision;
253
254
  if (settingsRevisions.get(engine) === revision)
254
255
  return;
255
- const config = compositionModelConfig(applied.composition, applied.connections);
256
- const gateway = trackSettingsGateway(new LoggingModelGateway(createModelGatewayFromConfig(config), communicationLogger), revision, [applied.composition.main.api, applied.composition.image.api, applied.composition.search.api]);
256
+ const routed = createCompositionGateway(applied.composition, applied.connections), config = routed.config;
257
+ const gateway = trackSettingsGateway(new LoggingModelGateway(routed.gateway, communicationLogger), revision, routed.heldConnections);
257
258
  engine.setModelProvider({ modelGateway: gateway, model: config?.model, reasoning: config?.defaultReasoning });
258
259
  if (config)
259
260
  effectiveModelProviders.set(engine, config.provider);
261
+ effectiveModelRoutes.set(engine, applied);
260
262
  registerCompositionTools(tools, applied.composition, applied.connections);
261
263
  for (const name of ["web_search", "image_create"]) {
262
264
  const tool = tools.get(name);
@@ -1542,10 +1544,17 @@ export class WebRepl {
1542
1544
  }
1543
1545
  const engine = this.runtime.engine;
1544
1546
  const nextModel = model.trim();
1545
- const provider = effectiveModelProviders.get(engine) ?? readModelProviderConfig()?.provider;
1546
- const metadata = (engine.getActiveModelCatalog?.() ?? loadModelCatalog()).models.find(m => m.modelIds.includes(nextModel));
1547
- if (metadata && provider && !modelProtocols(metadata).includes(provider))
1548
- return actionFailure("MODEL_INVALID", "模型不支持当前主连接接口");
1547
+ const routes = appliedRoutes(engine);
1548
+ if (routes) {
1549
+ if (!routeModel(nextModel, routes.composition, routes.connections))
1550
+ return actionFailure("MODEL_INVALID", "没有已启用的 API 提供此模型");
1551
+ }
1552
+ else {
1553
+ const provider = effectiveModelProviders.get(engine) ?? readModelProviderConfig()?.provider;
1554
+ const metadata = (engine.getActiveModelCatalog?.() ?? loadModelCatalog()).models.find(m => m.modelIds.includes(nextModel));
1555
+ if (metadata && provider && !modelProtocols(metadata).includes(provider))
1556
+ return actionFailure("MODEL_INVALID", "模型不支持当前主连接接口");
1557
+ }
1549
1558
  const current = { ...engine.getModelSettings(), ...engine.getPendingSessionSettings() };
1550
1559
  const argument = reasoning;
1551
1560
  const validationError = validateModelReasoningArgument(nextModel, argument);
@@ -3211,10 +3220,19 @@ function sanitizeWebAttachments(value) {
3211
3220
  });
3212
3221
  }
3213
3222
  const effectiveModelProviders = new WeakMap();
3223
+ const effectiveModelRoutes = new WeakMap();
3224
+ /** Applied priority list for this engine (or the stored one before its first turn); undefined for legacy/env setups. */
3225
+ function appliedRoutes(engine) {
3226
+ const applied = effectiveModelRoutes.get(engine) ?? new ModelSettingsStore().read()?.applied;
3227
+ return applied?.composition.order ? applied : undefined;
3228
+ }
3214
3229
  function webCatalog(runtime) {
3215
3230
  const catalog = runtime.engine.getActiveModelCatalog?.() ?? loadModelCatalog();
3216
3231
  const provider = effectiveModelProviders.get(runtime.engine) ?? readModelProviderConfig()?.provider;
3217
- const models = catalog.models.filter(model => !provider || modelProtocols(model).includes(provider));
3232
+ const routes = appliedRoutes(runtime.engine);
3233
+ const models = routes
3234
+ ? catalog.models.filter(model => routeModel(model.id, routes.composition, routes.connections))
3235
+ : catalog.models.filter(model => !provider || modelProtocols(model).includes(provider));
3218
3236
  const modelIds = [...new Set(models.flatMap(model => model.modelIds.length ? model.modelIds : [model.id]))].sort((left, right) => left.localeCompare(right, "en", { numeric: true }));
3219
3237
  return {
3220
3238
  commands: replCommandDefinitions,