neoctl 0.2.53 → 0.2.55

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 (81) hide show
  1. package/README.md +0 -1
  2. package/dist/agents/agent-activity.js +1 -1
  3. package/dist/agents/agent-activity.js.map +1 -1
  4. package/dist/agents/agent-tool.js +4 -4
  5. package/dist/agents/agent-tool.js.map +1 -1
  6. package/dist/core/context-metrics.js +2 -1
  7. package/dist/core/context-metrics.js.map +1 -1
  8. package/dist/core/query-engine.d.ts +13 -0
  9. package/dist/core/query-engine.js +98 -18
  10. package/dist/core/query-engine.js.map +1 -1
  11. package/dist/core/query.d.ts +1 -0
  12. package/dist/core/query.js +10 -1
  13. package/dist/core/query.js.map +1 -1
  14. package/dist/core/run-agent.js +45 -36
  15. package/dist/core/run-agent.js.map +1 -1
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.js +2 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/model/agent-settings-boundary.d.ts +11 -0
  20. package/dist/model/agent-settings-boundary.js +53 -0
  21. package/dist/model/agent-settings-boundary.js.map +1 -0
  22. package/dist/model/anthropic-adapter.d.ts +24 -0
  23. package/dist/model/anthropic-adapter.js +106 -0
  24. package/dist/model/anthropic-adapter.js.map +1 -0
  25. package/dist/model/anthropic-mapper.d.ts +14 -0
  26. package/dist/model/anthropic-mapper.js +364 -0
  27. package/dist/model/anthropic-mapper.js.map +1 -0
  28. package/dist/model/composition-runtime.d.ts +31 -0
  29. package/dist/model/composition-runtime.js +31 -0
  30. package/dist/model/composition-runtime.js.map +1 -0
  31. package/dist/model/config.d.ts +10 -3
  32. package/dist/model/config.js +26 -10
  33. package/dist/model/config.js.map +1 -1
  34. package/dist/model/context-window.d.ts +16 -1
  35. package/dist/model/context-window.js +171 -5
  36. package/dist/model/context-window.js.map +1 -1
  37. package/dist/model/env.js +0 -1
  38. package/dist/model/env.js.map +1 -1
  39. package/dist/model/model-gateway.d.ts +4 -1
  40. package/dist/model/model-gateway.js +4 -0
  41. package/dist/model/model-gateway.js.map +1 -1
  42. package/dist/model/model-metadata.json +10 -3
  43. package/dist/model/openai-adapter.js +2 -1
  44. package/dist/model/openai-adapter.js.map +1 -1
  45. package/dist/model/provider-factory.js +28 -1
  46. package/dist/model/provider-factory.js.map +1 -1
  47. package/dist/model/settings-files.d.ts +3 -0
  48. package/dist/model/settings-files.js +43 -0
  49. package/dist/model/settings-files.js.map +1 -0
  50. package/dist/model/settings-store.d.ts +85 -0
  51. package/dist/model/settings-store.js +235 -0
  52. package/dist/model/settings-store.js.map +1 -0
  53. package/dist/model/settings-sync.d.ts +31 -0
  54. package/dist/model/settings-sync.js +81 -0
  55. package/dist/model/settings-sync.js.map +1 -0
  56. package/dist/repl/commands.d.ts +1 -1
  57. package/dist/repl/commands.js +3 -2
  58. package/dist/repl/commands.js.map +1 -1
  59. package/dist/repl/index.js +51 -25
  60. package/dist/repl/index.js.map +1 -1
  61. package/dist/session/session-store.d.ts +11 -0
  62. package/dist/session/session-store.js +18 -1
  63. package/dist/session/session-store.js.map +1 -1
  64. package/dist/tasks/task-persistence.js +2 -1
  65. package/dist/tasks/task-persistence.js.map +1 -1
  66. package/dist/tools/builtins/image-generation-tool.js +2 -0
  67. package/dist/tools/builtins/image-generation-tool.js.map +1 -1
  68. package/dist/tools/builtins/search-providers.js +2 -0
  69. package/dist/tools/builtins/search-providers.js.map +1 -1
  70. package/dist/tools/builtins/search-tool.d.ts +2 -0
  71. package/dist/tools/builtins/search-tool.js +2 -2
  72. package/dist/tools/builtins/search-tool.js.map +1 -1
  73. package/dist/types/events.d.ts +1 -0
  74. package/dist/web/index.d.ts +9 -3
  75. package/dist/web/index.js +123 -32
  76. package/dist/web/index.js.map +1 -1
  77. package/dist/web/model-settings-api.d.ts +9 -0
  78. package/dist/web/model-settings-api.js +236 -0
  79. package/dist/web/model-settings-api.js.map +1 -0
  80. package/package.json +2 -2
  81. package/scripts/initialize-model-metadata.mjs +6 -0
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import { trackSettingsGateway } from "../model/settings-sync.js";
3
+ import { ModelSettingsStore, compositionModelConfig } from "../model/settings-store.js";
4
+ import { registerCompositionTools } from "../model/composition-runtime.js";
2
5
  import fs from "node:fs/promises";
3
6
  import { existsSync, readFileSync } from "node:fs";
4
7
  import path from "node:path";
@@ -12,7 +15,7 @@ import { getUserDotEnvPath, loadDefaultDotEnvFiles } from "../model/env.js";
12
15
  import { readModelProviderConfig } from "../model/config.js";
13
16
  import { findModelMetadata, loadModelCatalog, reasoningEffortsForModel, resolveContextWindowTokens } from "../model/context-window.js";
14
17
  import { CommunicationLogger, LoggingModelGateway } from "../model/communication-logger.js";
15
- import { createModelGatewayFromConfig, createModelGatewayFromProcessEnv } from "../model/provider-factory.js";
18
+ import { createModelGatewayFromConfig } from "../model/provider-factory.js";
16
19
  import { ToolRegistry } from "../tools/registry.js";
17
20
  import { editTool, writeTool } from "../tools/builtins/edit-tool.js";
18
21
  import { createExecTool, createWriteStdinTool } from "../tools/builtins/exec-tool.js";
@@ -233,9 +236,13 @@ async function buildSkillCatalogPromptSection(catalog) {
233
236
  }
234
237
  async function createRuntime(options = {}) {
235
238
  const envLoad = loadDefaultDotEnvFiles({ override: true });
236
- const modelConfig = readModelProviderConfig(process.env);
239
+ loadModelCatalog();
240
+ const settingsStore = new ModelSettingsStore();
241
+ const appliedSettings = settingsStore.read()?.applied;
242
+ const settingsRevisions = new WeakMap();
243
+ const modelConfig = appliedSettings ? compositionModelConfig(appliedSettings.composition, appliedSettings.connections) : readModelProviderConfig(process.env);
237
244
  const communicationLogger = new CommunicationLogger();
238
- const modelGateway = new LoggingModelGateway(createModelGatewayFromProcessEnv(process.env), communicationLogger);
245
+ const modelGateway = trackSettingsGateway(new LoggingModelGateway(createModelGatewayFromConfig(modelConfig), communicationLogger), appliedSettings?.revision, appliedSettings ? [appliedSettings.composition.main.api, appliedSettings.composition.image.api, appliedSettings.composition.search.api] : []);
239
246
  const taskStore = new TaskStore();
240
247
  const agentActivityStore = new AgentActivityStore();
241
248
  const secretStore = await SecretStore.open();
@@ -261,6 +268,8 @@ async function createRuntime(options = {}) {
261
268
  tools.register(createLoadImageTool());
262
269
  if (modelConfig?.provider === "openai")
263
270
  tools.register(createOpenAIImageGenerationTool());
271
+ if (appliedSettings)
272
+ registerCompositionTools(tools, appliedSettings.composition, appliedSettings.connections);
264
273
  tools.register(planTool);
265
274
  tools.register(createFrameworkFeedbackTool());
266
275
  for (const tool of createSecretTools())
@@ -289,6 +298,22 @@ async function createRuntime(options = {}) {
289
298
  reasoning: modelConfig?.defaultReasoning,
290
299
  modelGateway,
291
300
  tools,
301
+ beforeQuery: (engine) => {
302
+ const applied = settingsStore.read()?.applied;
303
+ if (!applied)
304
+ return;
305
+ const revision = applied.revision;
306
+ if (settingsRevisions.get(engine) === revision)
307
+ return;
308
+ const config = compositionModelConfig(applied.composition, applied.connections);
309
+ const gateway = trackSettingsGateway(new LoggingModelGateway(createModelGatewayFromConfig(config), communicationLogger), revision, [applied.composition.main.api, applied.composition.image.api, applied.composition.search.api]);
310
+ engine.setModelProvider({ modelGateway: gateway, model: config?.model, reasoning: config?.defaultReasoning });
311
+ registerCompositionTools(tools, applied.composition, applied.connections);
312
+ runtime.modelGateway = gateway;
313
+ runtime.agentRuntime.modelGateway = gateway;
314
+ runtime.defaultReasoning = config?.defaultReasoning;
315
+ settingsRevisions.set(engine, revision);
316
+ },
292
317
  contextManager: new SkillCatalogContextManager(skills),
293
318
  canUseTool: createSkillAwareCanUseTool(skills),
294
319
  secrets: secretStore,
@@ -882,7 +907,7 @@ function InkRepl({ runtime, initialCommandLine }) {
882
907
  };
883
908
  const handleEvent = (event) => {
884
909
  setStatus((current) => reduceStatus(current, event));
885
- if (event.type === "usage")
910
+ if (event.type === "usage" && !event.provisional)
886
911
  runtime.usage.add(event.usage);
887
912
  if (event.type === "state")
888
913
  return;
@@ -2661,7 +2686,7 @@ async function handleModelCommand(command, runtime) {
2661
2686
  reasoning: config.defaultReasoning,
2662
2687
  });
2663
2688
  syncImageGenerationTool(runtime, config.provider);
2664
- runtime.defaultReasoning = config.defaultReasoning;
2689
+ runtime.defaultReasoning = config?.defaultReasoning;
2665
2690
  }
2666
2691
  }
2667
2692
  }
@@ -2712,10 +2737,10 @@ async function persistModelCommandSettings(runtime, command, reasoningUpdate) {
2712
2737
  return { providerChanged: targetProvider !== currentProvider };
2713
2738
  }
2714
2739
  function currentModelProvider() {
2715
- return "openai";
2740
+ return parseLoginProvider(process.env.MODEL_PROVIDER) ?? "openai";
2716
2741
  }
2717
- function modelEnvKeyForProvider(_provider) {
2718
- return "OPENAI_MODEL";
2742
+ function modelEnvKeyForProvider(provider) {
2743
+ return provider === "anthropic" ? "ANTHROPIC_MODEL" : "OPENAI_MODEL";
2719
2744
  }
2720
2745
  function envValueForReasoning(reasoning) {
2721
2746
  if (reasoning === null)
@@ -3055,21 +3080,25 @@ function restoredHistoryLines(runtime) {
3055
3080
  }
3056
3081
  return lines;
3057
3082
  }
3058
- const LOGIN_PROVIDERS = ["openai"];
3083
+ const LOGIN_PROVIDERS = ["openai", "anthropic"];
3059
3084
  const SHARED_LOGIN_FIELDS = [
3060
3085
  { key: "reasoningEffort", label: "Reasoning effort", envKey: "MODEL_REASONING_EFFORT", scope: "shared", options: ["", "off", "none", "minimal", "low", "medium", "high", "xhigh", "max"] },
3061
- { key: "reasoningSummary", label: "Reasoning summary", envKey: "MODEL_REASONING_SUMMARY", scope: "shared", options: ["", "auto", "concise", "detailed"] },
3062
- { key: "maxOutputTokens", label: "Max output tokens", envKey: "MODEL_MAX_OUTPUT_TOKENS", scope: "shared" },
3086
+ { key: "maxOutputTokens", label: "Max output tokens", envKey: "MODEL_MAX_OUTPUT_TOKENS", scope: "shared", placeholder: "Leave empty for server default" },
3063
3087
  { key: "timeoutMs", label: "Timeout ms", envKey: "MODEL_TIMEOUT_MS", scope: "shared", placeholder: "120000" },
3064
3088
  { key: "streamIdleTimeoutMs", label: "Stream idle timeout ms", envKey: "MODEL_STREAM_IDLE_TIMEOUT_MS", scope: "shared", placeholder: "120000" },
3065
3089
  { key: "maxRetries", label: "Max retries", envKey: "MODEL_MAX_RETRIES", scope: "shared", placeholder: "2" },
3066
3090
  ];
3067
3091
  const LOGIN_FIELD_DEFINITIONS = {
3092
+ anthropic: [
3093
+ { key: "apiKey", label: "API / CPA key", envKey: "ANTHROPIC_API_KEY", scope: "provider", required: true, secret: true },
3094
+ { key: "baseUrl", label: "Base URL", envKey: "ANTHROPIC_BASE_URL", scope: "provider", placeholder: "https://api.anthropic.com" },
3095
+ { key: "model", label: "Model", envKey: "ANTHROPIC_MODEL", scope: "provider", required: true, placeholder: "claude-sonnet-4-6" },
3096
+ ...SHARED_LOGIN_FIELDS.map(field => field.key === "reasoningEffort" ? { ...field, options: ["", "off", "none", "low", "medium", "high", "xhigh", "max"] } : field.key === "maxOutputTokens" ? { ...field, placeholder: "8192" } : field),
3097
+ ],
3068
3098
  openai: [
3069
3099
  { key: "apiKey", label: "API key", envKey: "OPENAI_API_KEY", scope: "provider", required: true, secret: true, placeholder: "sk-..." },
3070
3100
  { key: "baseUrl", label: "Base URL", envKey: "OPENAI_BASE_URL", scope: "provider", placeholder: "https://api.openai.com" },
3071
3101
  { key: "model", label: "Model", envKey: "OPENAI_MODEL", scope: "provider", required: true, placeholder: "gpt-5.6" },
3072
- { key: "endpoint", label: "Endpoint", envKey: "OPENAI_ENDPOINT", scope: "provider", placeholder: "auto", options: ["auto", "responses", "chat"] },
3073
3102
  ...SHARED_LOGIN_FIELDS,
3074
3103
  ],
3075
3104
  };
@@ -3314,7 +3343,7 @@ async function submitLoginForm(state, runtime, append, setLoginFormState, setSta
3314
3343
  reasoning: config.defaultReasoning,
3315
3344
  });
3316
3345
  syncImageGenerationTool(runtime, config.provider);
3317
- runtime.defaultReasoning = config.defaultReasoning;
3346
+ runtime.defaultReasoning = config?.defaultReasoning;
3318
3347
  const metrics = await runtime.engine.contextMetrics();
3319
3348
  setStatus((current) => ({
3320
3349
  ...current,
@@ -3341,9 +3370,6 @@ function validateLoginForm(state) {
3341
3370
  if (value && !Number.isFinite(Number(value)))
3342
3371
  return `${fieldKey} must be a number.`;
3343
3372
  }
3344
- if (state.provider === "openai" && state.values.endpoint === "chat" && state.values.reasoningSummary?.trim()) {
3345
- return "Reasoning summary requires the Responses API endpoint.";
3346
- }
3347
3373
  return undefined;
3348
3374
  }
3349
3375
  function createLoginFormState(envPath = getUserDotEnvPath()) {
@@ -3373,23 +3399,21 @@ function loginValuesForProvider(provider, env) {
3373
3399
  values.baseUrl = defaultBaseUrlForLoginProvider(provider);
3374
3400
  if (!values.model)
3375
3401
  values.model = defaultModelForLoginProvider(provider);
3376
- if (provider === "openai" && !values.endpoint)
3377
- values.endpoint = "auto";
3378
3402
  return values;
3379
3403
  }
3380
3404
  function parseLoginProvider(value) {
3381
- if (value === "openai")
3405
+ if (value === "openai" || value === "anthropic")
3382
3406
  return value;
3383
3407
  return undefined;
3384
3408
  }
3385
- function guessLoginProvider(_env) {
3386
- return "openai";
3409
+ function guessLoginProvider(env) {
3410
+ return env.ANTHROPIC_API_KEY && !env.OPENAI_API_KEY ? "anthropic" : currentModelProvider();
3387
3411
  }
3388
- function defaultBaseUrlForLoginProvider(_provider) {
3389
- return "https://api.openai.com";
3412
+ function defaultBaseUrlForLoginProvider(provider) {
3413
+ return provider === "anthropic" ? "https://api.anthropic.com" : "https://api.openai.com";
3390
3414
  }
3391
- function defaultModelForLoginProvider(_provider) {
3392
- return "gpt-5.6";
3415
+ function defaultModelForLoginProvider(provider) {
3416
+ return provider === "anthropic" ? "claude-sonnet-4-6" : "gpt-5.6";
3393
3417
  }
3394
3418
  function loginFormViewHeight(state) {
3395
3419
  return state.step === "provider" ? state.providers.length + 3 : LOGIN_FIELD_DEFINITIONS[state.provider].length + 4;
@@ -3459,6 +3483,7 @@ function updateEnvContent(content, updates, removeKeys = []) {
3459
3483
  const grouped = groupLoginEnvEntries(missing);
3460
3484
  appendEnvGroup(updatedLines, "# Neo active provider", grouped.active);
3461
3485
  appendEnvGroup(updatedLines, "# OpenAI provider settings", grouped.openai);
3486
+ appendEnvGroup(updatedLines, "# Anthropic provider settings", grouped.anthropic);
3462
3487
  appendEnvGroup(updatedLines, "# Shared model runtime settings", grouped.shared);
3463
3488
  }
3464
3489
  return `${updatedLines.join("\n").replace(/\n*$/u, "")}\n`;
@@ -3467,6 +3492,7 @@ function groupLoginEnvEntries(entries) {
3467
3492
  return {
3468
3493
  active: entries.filter(([key]) => key === "MODEL_PROVIDER"),
3469
3494
  openai: entries.filter(([key]) => key.startsWith("OPENAI_")),
3495
+ anthropic: entries.filter(([key]) => key.startsWith("ANTHROPIC_")),
3470
3496
  shared: entries.filter(([key]) => key.startsWith("MODEL_") && key !== "MODEL_PROVIDER"),
3471
3497
  };
3472
3498
  }