neoctl 0.2.53 → 0.2.54

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 (76) hide show
  1. package/README.md +0 -1
  2. package/dist/agents/agent-tool.js +4 -4
  3. package/dist/agents/agent-tool.js.map +1 -1
  4. package/dist/core/query-engine.d.ts +10 -0
  5. package/dist/core/query-engine.js +72 -16
  6. package/dist/core/query-engine.js.map +1 -1
  7. package/dist/core/query.d.ts +1 -0
  8. package/dist/core/query.js +5 -0
  9. package/dist/core/query.js.map +1 -1
  10. package/dist/core/run-agent.js +45 -36
  11. package/dist/core/run-agent.js.map +1 -1
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +2 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/model/agent-settings-boundary.d.ts +11 -0
  16. package/dist/model/agent-settings-boundary.js +52 -0
  17. package/dist/model/agent-settings-boundary.js.map +1 -0
  18. package/dist/model/anthropic-adapter.d.ts +24 -0
  19. package/dist/model/anthropic-adapter.js +106 -0
  20. package/dist/model/anthropic-adapter.js.map +1 -0
  21. package/dist/model/anthropic-mapper.d.ts +14 -0
  22. package/dist/model/anthropic-mapper.js +340 -0
  23. package/dist/model/anthropic-mapper.js.map +1 -0
  24. package/dist/model/composition-runtime.d.ts +31 -0
  25. package/dist/model/composition-runtime.js +31 -0
  26. package/dist/model/composition-runtime.js.map +1 -0
  27. package/dist/model/config.d.ts +10 -3
  28. package/dist/model/config.js +26 -10
  29. package/dist/model/config.js.map +1 -1
  30. package/dist/model/context-window.d.ts +16 -1
  31. package/dist/model/context-window.js +171 -5
  32. package/dist/model/context-window.js.map +1 -1
  33. package/dist/model/env.js +0 -1
  34. package/dist/model/env.js.map +1 -1
  35. package/dist/model/model-gateway.d.ts +3 -1
  36. package/dist/model/model-gateway.js +4 -0
  37. package/dist/model/model-gateway.js.map +1 -1
  38. package/dist/model/model-metadata.json +9 -3
  39. package/dist/model/openai-adapter.js +2 -1
  40. package/dist/model/openai-adapter.js.map +1 -1
  41. package/dist/model/provider-factory.js +28 -1
  42. package/dist/model/provider-factory.js.map +1 -1
  43. package/dist/model/settings-files.d.ts +3 -0
  44. package/dist/model/settings-files.js +43 -0
  45. package/dist/model/settings-files.js.map +1 -0
  46. package/dist/model/settings-store.d.ts +84 -0
  47. package/dist/model/settings-store.js +191 -0
  48. package/dist/model/settings-store.js.map +1 -0
  49. package/dist/model/settings-sync.d.ts +23 -0
  50. package/dist/model/settings-sync.js +68 -0
  51. package/dist/model/settings-sync.js.map +1 -0
  52. package/dist/repl/commands.d.ts +1 -1
  53. package/dist/repl/commands.js +3 -2
  54. package/dist/repl/commands.js.map +1 -1
  55. package/dist/repl/index.js +50 -22
  56. package/dist/repl/index.js.map +1 -1
  57. package/dist/session/session-store.d.ts +2 -0
  58. package/dist/session/session-store.js +7 -1
  59. package/dist/session/session-store.js.map +1 -1
  60. package/dist/tasks/task-persistence.js +2 -1
  61. package/dist/tasks/task-persistence.js.map +1 -1
  62. package/dist/tools/builtins/image-generation-tool.js +2 -0
  63. package/dist/tools/builtins/image-generation-tool.js.map +1 -1
  64. package/dist/tools/builtins/search-providers.js +2 -0
  65. package/dist/tools/builtins/search-providers.js.map +1 -1
  66. package/dist/tools/builtins/search-tool.d.ts +2 -0
  67. package/dist/tools/builtins/search-tool.js +2 -2
  68. package/dist/tools/builtins/search-tool.js.map +1 -1
  69. package/dist/web/index.d.ts +9 -3
  70. package/dist/web/index.js +121 -29
  71. package/dist/web/index.js.map +1 -1
  72. package/dist/web/model-settings-api.d.ts +9 -0
  73. package/dist/web/model-settings-api.js +221 -0
  74. package/dist/web/model-settings-api.js.map +1 -0
  75. package/package.json +2 -2
  76. 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);
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,24 @@ 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
+ if (!config)
310
+ return;
311
+ const gateway = trackSettingsGateway(new LoggingModelGateway(createModelGatewayFromConfig(config), communicationLogger), revision);
312
+ engine.setModelProvider({ modelGateway: gateway, model: config.model, reasoning: config.defaultReasoning });
313
+ registerCompositionTools(tools, applied.composition, applied.connections);
314
+ runtime.modelGateway = gateway;
315
+ runtime.agentRuntime.modelGateway = gateway;
316
+ runtime.defaultReasoning = config.defaultReasoning;
317
+ settingsRevisions.set(engine, revision);
318
+ },
292
319
  contextManager: new SkillCatalogContextManager(skills),
293
320
  canUseTool: createSkillAwareCanUseTool(skills),
294
321
  secrets: secretStore,
@@ -2712,10 +2739,10 @@ async function persistModelCommandSettings(runtime, command, reasoningUpdate) {
2712
2739
  return { providerChanged: targetProvider !== currentProvider };
2713
2740
  }
2714
2741
  function currentModelProvider() {
2715
- return "openai";
2742
+ return parseLoginProvider(process.env.MODEL_PROVIDER) ?? "openai";
2716
2743
  }
2717
- function modelEnvKeyForProvider(_provider) {
2718
- return "OPENAI_MODEL";
2744
+ function modelEnvKeyForProvider(provider) {
2745
+ return provider === "anthropic" ? "ANTHROPIC_MODEL" : "OPENAI_MODEL";
2719
2746
  }
2720
2747
  function envValueForReasoning(reasoning) {
2721
2748
  if (reasoning === null)
@@ -3055,21 +3082,25 @@ function restoredHistoryLines(runtime) {
3055
3082
  }
3056
3083
  return lines;
3057
3084
  }
3058
- const LOGIN_PROVIDERS = ["openai"];
3085
+ const LOGIN_PROVIDERS = ["openai", "anthropic"];
3059
3086
  const SHARED_LOGIN_FIELDS = [
3060
3087
  { 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" },
3088
+ { key: "maxOutputTokens", label: "Max output tokens", envKey: "MODEL_MAX_OUTPUT_TOKENS", scope: "shared", placeholder: "Leave empty for server default" },
3063
3089
  { key: "timeoutMs", label: "Timeout ms", envKey: "MODEL_TIMEOUT_MS", scope: "shared", placeholder: "120000" },
3064
3090
  { key: "streamIdleTimeoutMs", label: "Stream idle timeout ms", envKey: "MODEL_STREAM_IDLE_TIMEOUT_MS", scope: "shared", placeholder: "120000" },
3065
3091
  { key: "maxRetries", label: "Max retries", envKey: "MODEL_MAX_RETRIES", scope: "shared", placeholder: "2" },
3066
3092
  ];
3067
3093
  const LOGIN_FIELD_DEFINITIONS = {
3094
+ anthropic: [
3095
+ { key: "apiKey", label: "API / CPA key", envKey: "ANTHROPIC_API_KEY", scope: "provider", required: true, secret: true },
3096
+ { key: "baseUrl", label: "Base URL", envKey: "ANTHROPIC_BASE_URL", scope: "provider", placeholder: "https://api.anthropic.com" },
3097
+ { key: "model", label: "Model", envKey: "ANTHROPIC_MODEL", scope: "provider", required: true, placeholder: "claude-sonnet-4-6" },
3098
+ ...SHARED_LOGIN_FIELDS.map(field => field.key === "reasoningEffort" ? { ...field, options: ["", "off", "none", "low", "medium", "high", "xhigh", "max"] } : field.key === "maxOutputTokens" ? { ...field, placeholder: "8192" } : field),
3099
+ ],
3068
3100
  openai: [
3069
3101
  { key: "apiKey", label: "API key", envKey: "OPENAI_API_KEY", scope: "provider", required: true, secret: true, placeholder: "sk-..." },
3070
3102
  { key: "baseUrl", label: "Base URL", envKey: "OPENAI_BASE_URL", scope: "provider", placeholder: "https://api.openai.com" },
3071
3103
  { 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
3104
  ...SHARED_LOGIN_FIELDS,
3074
3105
  ],
3075
3106
  };
@@ -3341,9 +3372,6 @@ function validateLoginForm(state) {
3341
3372
  if (value && !Number.isFinite(Number(value)))
3342
3373
  return `${fieldKey} must be a number.`;
3343
3374
  }
3344
- if (state.provider === "openai" && state.values.endpoint === "chat" && state.values.reasoningSummary?.trim()) {
3345
- return "Reasoning summary requires the Responses API endpoint.";
3346
- }
3347
3375
  return undefined;
3348
3376
  }
3349
3377
  function createLoginFormState(envPath = getUserDotEnvPath()) {
@@ -3373,23 +3401,21 @@ function loginValuesForProvider(provider, env) {
3373
3401
  values.baseUrl = defaultBaseUrlForLoginProvider(provider);
3374
3402
  if (!values.model)
3375
3403
  values.model = defaultModelForLoginProvider(provider);
3376
- if (provider === "openai" && !values.endpoint)
3377
- values.endpoint = "auto";
3378
3404
  return values;
3379
3405
  }
3380
3406
  function parseLoginProvider(value) {
3381
- if (value === "openai")
3407
+ if (value === "openai" || value === "anthropic")
3382
3408
  return value;
3383
3409
  return undefined;
3384
3410
  }
3385
- function guessLoginProvider(_env) {
3386
- return "openai";
3411
+ function guessLoginProvider(env) {
3412
+ return env.ANTHROPIC_API_KEY && !env.OPENAI_API_KEY ? "anthropic" : currentModelProvider();
3387
3413
  }
3388
- function defaultBaseUrlForLoginProvider(_provider) {
3389
- return "https://api.openai.com";
3414
+ function defaultBaseUrlForLoginProvider(provider) {
3415
+ return provider === "anthropic" ? "https://api.anthropic.com" : "https://api.openai.com";
3390
3416
  }
3391
- function defaultModelForLoginProvider(_provider) {
3392
- return "gpt-5.6";
3417
+ function defaultModelForLoginProvider(provider) {
3418
+ return provider === "anthropic" ? "claude-sonnet-4-6" : "gpt-5.6";
3393
3419
  }
3394
3420
  function loginFormViewHeight(state) {
3395
3421
  return state.step === "provider" ? state.providers.length + 3 : LOGIN_FIELD_DEFINITIONS[state.provider].length + 4;
@@ -3459,6 +3485,7 @@ function updateEnvContent(content, updates, removeKeys = []) {
3459
3485
  const grouped = groupLoginEnvEntries(missing);
3460
3486
  appendEnvGroup(updatedLines, "# Neo active provider", grouped.active);
3461
3487
  appendEnvGroup(updatedLines, "# OpenAI provider settings", grouped.openai);
3488
+ appendEnvGroup(updatedLines, "# Anthropic provider settings", grouped.anthropic);
3462
3489
  appendEnvGroup(updatedLines, "# Shared model runtime settings", grouped.shared);
3463
3490
  }
3464
3491
  return `${updatedLines.join("\n").replace(/\n*$/u, "")}\n`;
@@ -3467,6 +3494,7 @@ function groupLoginEnvEntries(entries) {
3467
3494
  return {
3468
3495
  active: entries.filter(([key]) => key === "MODEL_PROVIDER"),
3469
3496
  openai: entries.filter(([key]) => key.startsWith("OPENAI_")),
3497
+ anthropic: entries.filter(([key]) => key.startsWith("ANTHROPIC_")),
3470
3498
  shared: entries.filter(([key]) => key.startsWith("MODEL_") && key !== "MODEL_PROVIDER"),
3471
3499
  };
3472
3500
  }