mcoda 0.1.72 → 0.1.73
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"AA+lBA,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA8YhD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AgentsApi, WorkspaceResolver } from "@mcoda/core";
|
|
2
|
+
import { defaultLocalRunnerKindForAdapter, isLocalOpenAiCompatibleAdapter, isReservedLocalRunnerExtraBodyKey, isSecretLocalRunnerHeaderKey, normalizeLocalRunnerAuthMode, normalizeLocalRunnerKind, normalizeLocalRunnerResponseFormatStrategy, } from "@mcoda/shared";
|
|
2
3
|
import readline from "node:readline";
|
|
3
4
|
const parseArgs = (argv) => {
|
|
4
5
|
const flags = {};
|
|
@@ -49,7 +50,7 @@ Subcommands:
|
|
|
49
50
|
limits Show tracked usage-limit windows/reset times
|
|
50
51
|
--agent <NAME> Filter by agent slug/id
|
|
51
52
|
add <NAME> Create a global agent
|
|
52
|
-
--adapter <TYPE> Adapter slug (openai-api|zhipu-api|codex-cli|claude-cli|gemini-cli|local-model|qa-cli|ollama-remote)
|
|
53
|
+
--adapter <TYPE> Adapter slug (openai-api|zhipu-api|codex-cli|claude-cli|gemini-cli|local-model|qa-cli|ollama-remote|openai-compatible-local|vllm-local|llama-cpp-local|llamacpp-local)
|
|
53
54
|
--model <MODEL> Default model name
|
|
54
55
|
--rating <N> Relative capability rating (higher is stronger)
|
|
55
56
|
--reasoning-rating <N> Relative reasoning strength rating (higher is stronger)
|
|
@@ -64,14 +65,42 @@ Subcommands:
|
|
|
64
65
|
--job-path <PATH> Optional job prompt path
|
|
65
66
|
--character-path <PATH> Optional character prompt path
|
|
66
67
|
--config-base-url <URL> Base URL for remote adapters (e.g., http://host:11434 for ollama-remote)
|
|
68
|
+
--config-runner-kind <K> Local runner kind (vllm|llama-cpp|llama-cpp-python|lm-studio|localai|sglang|tgi|custom)
|
|
69
|
+
--config-auth-mode <M> Local auth mode (none|bearer|dummy-bearer)
|
|
70
|
+
--config-dummy-bearer-token <T> Non-secret dummy bearer token for local runners
|
|
71
|
+
--config-header <K=V> Repeatable non-secret local runner header
|
|
72
|
+
--config-extra-body-json <JSON> Extra OpenAI-compatible request body object
|
|
73
|
+
--config-response-format-strategy <S> Local response format strategy
|
|
74
|
+
--config-health-path <P> Local runner health path override
|
|
75
|
+
--config-models-path <P> Local runner models path override
|
|
67
76
|
--config-temperature <N> Temperature override for supported adapters
|
|
68
77
|
--config-thinking <BOOL> Enable thinking mode for supported adapters
|
|
69
78
|
update <NAME> Update adapter/model/capabilities/prompts for an agent
|
|
79
|
+
--adapter <TYPE> Adapter slug (supports local OpenAI-compatible aliases)
|
|
80
|
+
--model <MODEL> Default model name
|
|
81
|
+
--rating <N> Relative capability rating (higher is stronger)
|
|
82
|
+
--reasoning-rating <N> Relative reasoning strength rating (higher is stronger)
|
|
70
83
|
--max-complexity <N> Max task complexity the agent should handle (1-10)
|
|
71
84
|
--openai-compatible <B> OpenAI-compatible API support (true/false)
|
|
72
85
|
--context-window <N> Context window size (tokens)
|
|
73
86
|
--max-output-tokens <N> Max output tokens per response
|
|
74
87
|
--supports-tools <B> Tool-calling support (true/false)
|
|
88
|
+
--best-usage <TEXT> Primary usage area (e.g., code_write, ui_ux_docs)
|
|
89
|
+
--cost-per-million <N> Cost per 1M tokens (0 for local models)
|
|
90
|
+
--capability <CAP> Repeatable capabilities to attach
|
|
91
|
+
--job-path <PATH> Optional job prompt path
|
|
92
|
+
--character-path <PATH> Optional character prompt path
|
|
93
|
+
--config-base-url <URL> Base URL for remote/local runner adapters
|
|
94
|
+
--config-runner-kind <K> Local runner kind (vllm|llama-cpp|llama-cpp-python|lm-studio|localai|sglang|tgi|custom)
|
|
95
|
+
--config-auth-mode <M> Local auth mode (none|bearer|dummy-bearer)
|
|
96
|
+
--config-dummy-bearer-token <T> Non-secret dummy bearer token for local runners
|
|
97
|
+
--config-header <K=V> Repeatable non-secret local runner header
|
|
98
|
+
--config-extra-body-json <JSON> Extra OpenAI-compatible request body object
|
|
99
|
+
--config-response-format-strategy <S> Local response format strategy
|
|
100
|
+
--config-health-path <P> Local runner health path override
|
|
101
|
+
--config-models-path <P> Local runner models path override
|
|
102
|
+
--config-temperature <N> Temperature override for supported adapters
|
|
103
|
+
--config-thinking <BOOL> Enable thinking mode for supported adapters
|
|
75
104
|
delete|remove <NAME> Remove an agent (use --force to ignore routing/default references)
|
|
76
105
|
--force Force deletion even if referenced
|
|
77
106
|
auth set <NAME> Store credentials (use --api-key or interactive prompt)
|
|
@@ -161,6 +190,74 @@ const parseBooleanFlag = (value, label) => {
|
|
|
161
190
|
return false;
|
|
162
191
|
throw new Error(`Invalid ${label}; expected true/false`);
|
|
163
192
|
};
|
|
193
|
+
const CONFIG_FLAG_NAMES = [
|
|
194
|
+
"config-base-url",
|
|
195
|
+
"config-runner-kind",
|
|
196
|
+
"config-auth-mode",
|
|
197
|
+
"config-dummy-bearer-token",
|
|
198
|
+
"config-header",
|
|
199
|
+
"config-extra-body-json",
|
|
200
|
+
"config-response-format-strategy",
|
|
201
|
+
"config-health-path",
|
|
202
|
+
"config-models-path",
|
|
203
|
+
"config-temperature",
|
|
204
|
+
"config-thinking",
|
|
205
|
+
];
|
|
206
|
+
const hasConfigFlags = (flags) => CONFIG_FLAG_NAMES.some((flagName) => flags[flagName] !== undefined);
|
|
207
|
+
const getLastStringFlag = (value, label) => {
|
|
208
|
+
if (value === undefined)
|
|
209
|
+
return undefined;
|
|
210
|
+
const raw = Array.isArray(value) ? value[value.length - 1] : value;
|
|
211
|
+
if (typeof raw === "boolean") {
|
|
212
|
+
throw new Error(`Invalid ${label}; expected a value`);
|
|
213
|
+
}
|
|
214
|
+
const trimmed = String(raw).trim();
|
|
215
|
+
if (!trimmed) {
|
|
216
|
+
throw new Error(`Invalid ${label}; expected a non-empty value`);
|
|
217
|
+
}
|
|
218
|
+
return trimmed;
|
|
219
|
+
};
|
|
220
|
+
const getStringFlagValues = (value, label) => {
|
|
221
|
+
if (value === undefined)
|
|
222
|
+
return [];
|
|
223
|
+
const values = Array.isArray(value) ? value : [value];
|
|
224
|
+
return values.map((raw) => {
|
|
225
|
+
if (typeof raw === "boolean") {
|
|
226
|
+
throw new Error(`Invalid ${label}; expected a value`);
|
|
227
|
+
}
|
|
228
|
+
const trimmed = String(raw).trim();
|
|
229
|
+
if (!trimmed) {
|
|
230
|
+
throw new Error(`Invalid ${label}; expected a non-empty value`);
|
|
231
|
+
}
|
|
232
|
+
return trimmed;
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
const validateHttpUrl = (value, label) => {
|
|
236
|
+
let parsed;
|
|
237
|
+
try {
|
|
238
|
+
parsed = new URL(value);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
throw new Error(`Invalid ${label}; expected an absolute http(s) URL`);
|
|
242
|
+
}
|
|
243
|
+
if (!["http:", "https:"].includes(parsed.protocol) || !parsed.hostname) {
|
|
244
|
+
throw new Error(`Invalid ${label}; expected an absolute http(s) URL`);
|
|
245
|
+
}
|
|
246
|
+
return value;
|
|
247
|
+
};
|
|
248
|
+
const isLoopbackBaseUrl = (value) => {
|
|
249
|
+
try {
|
|
250
|
+
const hostname = new URL(value).hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
251
|
+
if (hostname === "localhost" || hostname === "::1")
|
|
252
|
+
return true;
|
|
253
|
+
if (/^127(?:\.\d{1,3}){3}$/.test(hostname))
|
|
254
|
+
return true;
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
164
261
|
const resolveListRefreshHealth = (flags) => {
|
|
165
262
|
const refreshHealth = parseBooleanFlag(flags["refresh-health"], "--refresh-health");
|
|
166
263
|
const noRefreshHealth = parseBooleanFlag(flags["no-refresh-health"], "--no-refresh-health");
|
|
@@ -185,10 +282,98 @@ const parseCostPerMillion = (value) => {
|
|
|
185
282
|
}
|
|
186
283
|
return parsed;
|
|
187
284
|
};
|
|
188
|
-
const
|
|
285
|
+
const parseConfigExtraBody = (raw) => {
|
|
286
|
+
let parsed;
|
|
287
|
+
try {
|
|
288
|
+
parsed = JSON.parse(raw);
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
throw new Error("Invalid --config-extra-body-json; expected a JSON object");
|
|
292
|
+
}
|
|
293
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
294
|
+
throw new Error("Invalid --config-extra-body-json; expected a JSON object");
|
|
295
|
+
}
|
|
296
|
+
for (const key of Object.keys(parsed)) {
|
|
297
|
+
if (isReservedLocalRunnerExtraBodyKey(key)) {
|
|
298
|
+
throw new Error(`Invalid --config-extra-body-json; reserved OpenAI request key "${key}" is not allowed`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return parsed;
|
|
302
|
+
};
|
|
303
|
+
const parseConfigHeaders = (value) => {
|
|
304
|
+
const entries = getStringFlagValues(value, "--config-header");
|
|
305
|
+
if (entries.length === 0)
|
|
306
|
+
return undefined;
|
|
307
|
+
const headers = {};
|
|
308
|
+
for (const entry of entries) {
|
|
309
|
+
const separatorIndex = entry.indexOf("=");
|
|
310
|
+
if (separatorIndex <= 0) {
|
|
311
|
+
throw new Error("Invalid --config-header; expected key=value");
|
|
312
|
+
}
|
|
313
|
+
const key = entry.slice(0, separatorIndex).trim();
|
|
314
|
+
const headerValue = entry.slice(separatorIndex + 1).trim();
|
|
315
|
+
if (!key || !headerValue) {
|
|
316
|
+
throw new Error("Invalid --config-header; expected non-empty key=value");
|
|
317
|
+
}
|
|
318
|
+
if (isSecretLocalRunnerHeaderKey(key)) {
|
|
319
|
+
throw new Error(`Invalid --config-header; secret-bearing header "${key}" must be stored as auth, not config`);
|
|
320
|
+
}
|
|
321
|
+
headers[key] = headerValue;
|
|
322
|
+
}
|
|
323
|
+
return Object.keys(headers).length ? headers : undefined;
|
|
324
|
+
};
|
|
325
|
+
const parseConfig = (flags, options = {}) => {
|
|
189
326
|
const config = {};
|
|
190
|
-
|
|
191
|
-
|
|
327
|
+
const localOpenAiCompatible = isLocalOpenAiCompatibleAdapter(options.adapter);
|
|
328
|
+
const applyLocalDefaults = options.applyLocalDefaults ?? true;
|
|
329
|
+
const baseUrl = getLastStringFlag(flags["config-base-url"], "--config-base-url");
|
|
330
|
+
if (baseUrl)
|
|
331
|
+
config.baseUrl = validateHttpUrl(baseUrl, "--config-base-url");
|
|
332
|
+
const runnerKindValue = getLastStringFlag(flags["config-runner-kind"], "--config-runner-kind");
|
|
333
|
+
if (runnerKindValue) {
|
|
334
|
+
const runnerKind = normalizeLocalRunnerKind(runnerKindValue);
|
|
335
|
+
if (!runnerKind)
|
|
336
|
+
throw new Error(`Invalid --config-runner-kind; unknown local runner kind "${runnerKindValue}"`);
|
|
337
|
+
config.runnerKind = runnerKind;
|
|
338
|
+
}
|
|
339
|
+
else if (applyLocalDefaults) {
|
|
340
|
+
const defaultRunnerKind = defaultLocalRunnerKindForAdapter(options.adapter);
|
|
341
|
+
if (defaultRunnerKind)
|
|
342
|
+
config.runnerKind = defaultRunnerKind;
|
|
343
|
+
}
|
|
344
|
+
const authModeValue = getLastStringFlag(flags["config-auth-mode"], "--config-auth-mode");
|
|
345
|
+
if (authModeValue) {
|
|
346
|
+
const authMode = normalizeLocalRunnerAuthMode(authModeValue);
|
|
347
|
+
if (!authMode)
|
|
348
|
+
throw new Error(`Invalid --config-auth-mode; unknown local auth mode "${authModeValue}"`);
|
|
349
|
+
config.authMode = authMode;
|
|
350
|
+
}
|
|
351
|
+
else if (localOpenAiCompatible && applyLocalDefaults) {
|
|
352
|
+
config.authMode = "none";
|
|
353
|
+
}
|
|
354
|
+
const dummyBearerToken = getLastStringFlag(flags["config-dummy-bearer-token"], "--config-dummy-bearer-token");
|
|
355
|
+
if (dummyBearerToken)
|
|
356
|
+
config.dummyBearerToken = dummyBearerToken;
|
|
357
|
+
const headers = parseConfigHeaders(flags["config-header"]);
|
|
358
|
+
if (headers)
|
|
359
|
+
config.headers = headers;
|
|
360
|
+
const extraBodyRaw = getLastStringFlag(flags["config-extra-body-json"], "--config-extra-body-json");
|
|
361
|
+
if (extraBodyRaw)
|
|
362
|
+
config.extraBody = parseConfigExtraBody(extraBodyRaw);
|
|
363
|
+
const responseFormatStrategyValue = getLastStringFlag(flags["config-response-format-strategy"], "--config-response-format-strategy");
|
|
364
|
+
if (responseFormatStrategyValue) {
|
|
365
|
+
const responseFormatStrategy = normalizeLocalRunnerResponseFormatStrategy(responseFormatStrategyValue);
|
|
366
|
+
if (!responseFormatStrategy) {
|
|
367
|
+
throw new Error(`Invalid --config-response-format-strategy; unknown response format strategy "${responseFormatStrategyValue}"`);
|
|
368
|
+
}
|
|
369
|
+
config.responseFormatStrategy = responseFormatStrategy;
|
|
370
|
+
}
|
|
371
|
+
const healthPath = getLastStringFlag(flags["config-health-path"], "--config-health-path");
|
|
372
|
+
if (healthPath)
|
|
373
|
+
config.healthPath = healthPath;
|
|
374
|
+
const modelsPath = getLastStringFlag(flags["config-models-path"], "--config-models-path");
|
|
375
|
+
if (modelsPath)
|
|
376
|
+
config.modelsPath = modelsPath;
|
|
192
377
|
if (flags["config-temperature"] !== undefined) {
|
|
193
378
|
const raw = flags["config-temperature"];
|
|
194
379
|
const parsed = typeof raw === "number" ? raw : Number.parseFloat(String(raw));
|
|
@@ -215,8 +400,20 @@ const parseConfig = (flags) => {
|
|
|
215
400
|
}
|
|
216
401
|
}
|
|
217
402
|
}
|
|
403
|
+
if (options.requireBaseUrl && !config.baseUrl && !config.endpoint && !config.apiBaseUrl) {
|
|
404
|
+
throw new Error("CONFIG_REQUIRED: --config-base-url is required for local OpenAI-compatible adapters");
|
|
405
|
+
}
|
|
406
|
+
if (config.authMode === "none" && typeof config.baseUrl === "string" && !isLoopbackBaseUrl(config.baseUrl)) {
|
|
407
|
+
options.warn?.(`Warning: ${options.adapter ?? "local runner"} uses authMode=none with non-loopback baseUrl ${config.baseUrl}.`);
|
|
408
|
+
}
|
|
218
409
|
return Object.keys(config).length ? config : undefined;
|
|
219
410
|
};
|
|
411
|
+
const hasLocalRunnerBaseUrl = (config) => Boolean(config?.baseUrl || config?.endpoint || config?.apiBaseUrl);
|
|
412
|
+
const mergeConfigPatch = (existing, patch) => {
|
|
413
|
+
if (!patch)
|
|
414
|
+
return undefined;
|
|
415
|
+
return existing ? { ...existing, ...patch } : patch;
|
|
416
|
+
};
|
|
220
417
|
const DEFAULT_OLLAMA_CAPABILITIES = ["plan", "code_write", "code_review"];
|
|
221
418
|
const pad = (value, width) => value.padEnd(width, " ");
|
|
222
419
|
const truncate = (value, max) => {
|
|
@@ -554,22 +751,33 @@ export class AgentsCommands {
|
|
|
554
751
|
const name = parsed.positionals[0];
|
|
555
752
|
if (!name)
|
|
556
753
|
throw new Error("agent add requires a slug/name\n\n" + USAGE);
|
|
754
|
+
const adapter = String(parsed.flags.adapter ?? "openai-api");
|
|
755
|
+
const localOpenAiCompatible = isLocalOpenAiCompatibleAdapter(adapter);
|
|
557
756
|
const capabilities = parseCapabilities(parsed.flags.capability) ??
|
|
558
|
-
(
|
|
757
|
+
(adapter === "ollama-remote" ? DEFAULT_OLLAMA_CAPABILITIES : []);
|
|
559
758
|
const prompts = parsePrompts(parsed.flags);
|
|
560
|
-
const config = parseConfig(parsed.flags
|
|
759
|
+
const config = parseConfig(parsed.flags, {
|
|
760
|
+
adapter,
|
|
761
|
+
requireBaseUrl: localOpenAiCompatible,
|
|
762
|
+
warn: (message) => console.warn(message),
|
|
763
|
+
});
|
|
561
764
|
const rating = parseRating(parsed.flags.rating);
|
|
562
765
|
const reasoningRating = parseReasoningRating(parsed.flags["reasoning-rating"]);
|
|
563
766
|
const maxComplexity = parseMaxComplexity(parsed.flags["max-complexity"]);
|
|
564
|
-
const
|
|
767
|
+
const openaiCompatibleFlag = parseBooleanFlag(parsed.flags["openai-compatible"], "--openai-compatible");
|
|
768
|
+
if (localOpenAiCompatible && openaiCompatibleFlag === false) {
|
|
769
|
+
throw new Error("Local OpenAI-compatible adapters require --openai-compatible true");
|
|
770
|
+
}
|
|
771
|
+
const openaiCompatible = localOpenAiCompatible ? true : openaiCompatibleFlag;
|
|
565
772
|
const contextWindow = parsePositiveInt(parsed.flags["context-window"], "--context-window");
|
|
566
773
|
const maxOutputTokens = parsePositiveInt(parsed.flags["max-output-tokens"], "--max-output-tokens");
|
|
567
774
|
const supportsTools = parseBooleanFlag(parsed.flags["supports-tools"], "--supports-tools");
|
|
568
775
|
const bestUsage = parsed.flags["best-usage"] ? String(parsed.flags["best-usage"]) : undefined;
|
|
569
|
-
const
|
|
776
|
+
const parsedCostPerMillion = parseCostPerMillion(parsed.flags["cost-per-million"]);
|
|
777
|
+
const costPerMillion = localOpenAiCompatible && parsedCostPerMillion === undefined ? 0 : parsedCostPerMillion;
|
|
570
778
|
const agent = await api.createAgent({
|
|
571
779
|
slug: name,
|
|
572
|
-
adapter
|
|
780
|
+
adapter,
|
|
573
781
|
defaultModel: parsed.flags.model ? String(parsed.flags.model) : undefined,
|
|
574
782
|
rating,
|
|
575
783
|
reasoningRating,
|
|
@@ -592,20 +800,45 @@ export class AgentsCommands {
|
|
|
592
800
|
const name = parsed.positionals[0];
|
|
593
801
|
if (!name)
|
|
594
802
|
throw new Error("agent update requires a slug/name\n\n" + USAGE);
|
|
803
|
+
const existing = await api.getAgent(name);
|
|
804
|
+
const adapter = parsed.flags.adapter ? String(parsed.flags.adapter) : undefined;
|
|
805
|
+
const effectiveAdapter = adapter ?? existing.adapter;
|
|
806
|
+
const localOpenAiCompatible = isLocalOpenAiCompatibleAdapter(effectiveAdapter);
|
|
807
|
+
const switchingToLocalOpenAiCompatible = adapter !== undefined && isLocalOpenAiCompatibleAdapter(adapter);
|
|
595
808
|
const capabilities = parseCapabilities(parsed.flags.capability);
|
|
596
809
|
const prompts = parsePrompts(parsed.flags);
|
|
597
|
-
const
|
|
810
|
+
const configPatch = hasConfigFlags(parsed.flags) || switchingToLocalOpenAiCompatible
|
|
811
|
+
? parseConfig(parsed.flags, {
|
|
812
|
+
adapter: effectiveAdapter,
|
|
813
|
+
applyLocalDefaults: switchingToLocalOpenAiCompatible,
|
|
814
|
+
})
|
|
815
|
+
: undefined;
|
|
816
|
+
const existingConfig = existing.config && typeof existing.config === "object"
|
|
817
|
+
? existing.config
|
|
818
|
+
: undefined;
|
|
819
|
+
const config = mergeConfigPatch(existingConfig, configPatch);
|
|
820
|
+
if (config && localOpenAiCompatible && !hasLocalRunnerBaseUrl(config)) {
|
|
821
|
+
throw new Error("CONFIG_REQUIRED: --config-base-url is required for local OpenAI-compatible adapters");
|
|
822
|
+
}
|
|
823
|
+
if (config?.authMode === "none" && typeof config.baseUrl === "string" && !isLoopbackBaseUrl(config.baseUrl)) {
|
|
824
|
+
console.warn(`Warning: ${effectiveAdapter ?? "local runner"} uses authMode=none with non-loopback baseUrl ${config.baseUrl}.`);
|
|
825
|
+
}
|
|
598
826
|
const rating = parseRating(parsed.flags.rating);
|
|
599
827
|
const reasoningRating = parseReasoningRating(parsed.flags["reasoning-rating"]);
|
|
600
828
|
const maxComplexity = parseMaxComplexity(parsed.flags["max-complexity"]);
|
|
601
|
-
const
|
|
829
|
+
const openaiCompatibleFlag = parseBooleanFlag(parsed.flags["openai-compatible"], "--openai-compatible");
|
|
830
|
+
if (localOpenAiCompatible && openaiCompatibleFlag === false) {
|
|
831
|
+
throw new Error("Local OpenAI-compatible adapters require --openai-compatible true");
|
|
832
|
+
}
|
|
833
|
+
const openaiCompatible = localOpenAiCompatible ? true : openaiCompatibleFlag;
|
|
602
834
|
const contextWindow = parsePositiveInt(parsed.flags["context-window"], "--context-window");
|
|
603
835
|
const maxOutputTokens = parsePositiveInt(parsed.flags["max-output-tokens"], "--max-output-tokens");
|
|
604
836
|
const supportsTools = parseBooleanFlag(parsed.flags["supports-tools"], "--supports-tools");
|
|
605
837
|
const bestUsage = parsed.flags["best-usage"] ? String(parsed.flags["best-usage"]) : undefined;
|
|
606
|
-
const
|
|
838
|
+
const parsedCostPerMillion = parseCostPerMillion(parsed.flags["cost-per-million"]);
|
|
839
|
+
const costPerMillion = localOpenAiCompatible && parsedCostPerMillion === undefined ? 0 : parsedCostPerMillion;
|
|
607
840
|
const agent = await api.updateAgent(name, {
|
|
608
|
-
adapter
|
|
841
|
+
adapter,
|
|
609
842
|
defaultModel: parsed.flags.model ? String(parsed.flags.model) : undefined,
|
|
610
843
|
rating,
|
|
611
844
|
reasoningRating,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcoda",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.73",
|
|
4
4
|
"description": "Local-first CLI for planning, documentation, and execution workflows with agent assistance.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"yaml": "^2.4.2",
|
|
50
|
-
"@mcoda/core": "0.1.
|
|
51
|
-
"@mcoda/shared": "0.1.
|
|
50
|
+
"@mcoda/core": "0.1.73",
|
|
51
|
+
"@mcoda/shared": "0.1.73"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@mcoda/
|
|
55
|
-
"@mcoda/
|
|
54
|
+
"@mcoda/integrations": "0.1.73",
|
|
55
|
+
"@mcoda/db": "0.1.73"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsc -p tsconfig.json",
|