@mono-agent/agent-app 0.20.10 → 0.20.14
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/README.md +33 -18
- package/dist/app-config.d.ts +2 -2
- package/dist/app-controller-channels.d.ts +4 -0
- package/dist/app-controller-channels.d.ts.map +1 -1
- package/dist/app-controller-channels.js +20 -2
- package/dist/app-controller-channels.js.map +1 -1
- package/dist/app-controller-continuation.d.ts.map +1 -1
- package/dist/app-controller-continuation.js +2 -3
- package/dist/app-controller-continuation.js.map +1 -1
- package/dist/app-controller-lifecycle.d.ts +4 -0
- package/dist/app-controller-lifecycle.d.ts.map +1 -1
- package/dist/app-controller-lifecycle.js +7 -0
- package/dist/app-controller-lifecycle.js.map +1 -1
- package/dist/app-controller-monitors.d.ts +26 -0
- package/dist/app-controller-monitors.d.ts.map +1 -0
- package/dist/app-controller-monitors.js +127 -0
- package/dist/app-controller-monitors.js.map +1 -0
- package/dist/app-controller-responder.d.ts +7 -17
- package/dist/app-controller-responder.d.ts.map +1 -1
- package/dist/app-controller-responder.js +33 -69
- package/dist/app-controller-responder.js.map +1 -1
- package/dist/app-controller-utils.d.ts +1 -5
- package/dist/app-controller-utils.d.ts.map +1 -1
- package/dist/app-controller-utils.js +4 -21
- package/dist/app-controller-utils.js.map +1 -1
- package/dist/app-controller.d.ts +25 -11
- package/dist/app-controller.d.ts.map +1 -1
- package/dist/app-controller.js +36 -1
- package/dist/app-controller.js.map +1 -1
- package/dist/channel-drivers/slack.d.ts.map +1 -1
- package/dist/channel-drivers/slack.js +24 -0
- package/dist/channel-drivers/slack.js.map +1 -1
- package/dist/channel-drivers/telegram.d.ts.map +1 -1
- package/dist/channel-drivers/telegram.js +26 -0
- package/dist/channel-drivers/telegram.js.map +1 -1
- package/dist/channel-drivers/tui.d.ts +68 -8
- package/dist/channel-drivers/tui.d.ts.map +1 -1
- package/dist/channel-drivers/tui.js +388 -89
- package/dist/channel-drivers/tui.js.map +1 -1
- package/dist/channel-runtime-controls.d.ts +2 -1
- package/dist/channel-runtime-controls.d.ts.map +1 -1
- package/dist/channel-runtime-controls.js +79 -22
- package/dist/channel-runtime-controls.js.map +1 -1
- package/dist/cli-args.d.ts +4 -6
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +16 -36
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +11 -0
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli-help.d.ts +26 -0
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +25 -34
- package/dist/cli-help.js.map +1 -1
- package/dist/cli-init-command.d.ts +1 -2
- package/dist/cli-init-command.d.ts.map +1 -1
- package/dist/cli-init-command.js +5 -49
- package/dist/cli-init-command.js.map +1 -1
- package/dist/config-reference.d.ts.map +1 -1
- package/dist/config-reference.js +161 -52
- package/dist/config-reference.js.map +1 -1
- package/dist/configuration-proposal-tool.d.ts.map +1 -1
- package/dist/configuration-proposal-tool.js +3 -11
- package/dist/configuration-proposal-tool.js.map +1 -1
- package/dist/configured-agent.d.ts +18 -3
- package/dist/configured-agent.d.ts.map +1 -1
- package/dist/configured-agent.js +67 -86
- package/dist/configured-agent.js.map +1 -1
- package/dist/conversation-title.d.ts.map +1 -1
- package/dist/conversation-title.js +9 -2
- package/dist/conversation-title.js.map +1 -1
- package/dist/doctor.d.ts +7 -13
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +191 -725
- package/dist/doctor.js.map +1 -1
- package/dist/first-run-readiness.d.ts.map +1 -1
- package/dist/first-run-readiness.js +0 -6
- package/dist/first-run-readiness.js.map +1 -1
- package/dist/local-configuration.d.ts.map +1 -1
- package/dist/local-configuration.js +9 -37
- package/dist/local-configuration.js.map +1 -1
- package/dist/memory-remember.d.ts +49 -0
- package/dist/memory-remember.d.ts.map +1 -0
- package/dist/memory-remember.js +190 -0
- package/dist/memory-remember.js.map +1 -0
- package/dist/memory-retrieval.d.ts +24 -0
- package/dist/memory-retrieval.d.ts.map +1 -1
- package/dist/memory-retrieval.js +23 -0
- package/dist/memory-retrieval.js.map +1 -1
- package/dist/model-effort-capabilities.d.ts +8 -9
- package/dist/model-effort-capabilities.d.ts.map +1 -1
- package/dist/model-effort-capabilities.js +17 -35
- package/dist/model-effort-capabilities.js.map +1 -1
- package/dist/modules/base.d.ts +3 -4
- package/dist/modules/base.d.ts.map +1 -1
- package/dist/modules/base.js +3 -5
- package/dist/modules/base.js.map +1 -1
- package/dist/modules/catalog.d.ts.map +1 -1
- package/dist/modules/catalog.js +11 -9
- package/dist/modules/catalog.js.map +1 -1
- package/dist/modules/known-tools.d.ts +2 -2
- package/dist/modules/known-tools.d.ts.map +1 -1
- package/dist/modules/known-tools.js +6 -0
- package/dist/modules/known-tools.js.map +1 -1
- package/dist/monitor-channel-routing.d.ts +20 -0
- package/dist/monitor-channel-routing.d.ts.map +1 -0
- package/dist/monitor-channel-routing.js +73 -0
- package/dist/monitor-channel-routing.js.map +1 -0
- package/dist/monitors-command.d.ts +23 -0
- package/dist/monitors-command.d.ts.map +1 -0
- package/dist/monitors-command.js +207 -0
- package/dist/monitors-command.js.map +1 -0
- package/dist/monitors-config.d.ts +74 -0
- package/dist/monitors-config.d.ts.map +1 -0
- package/dist/monitors-config.js +146 -0
- package/dist/monitors-config.js.map +1 -0
- package/dist/monitors-context.d.ts +58 -0
- package/dist/monitors-context.d.ts.map +1 -0
- package/dist/monitors-context.js +182 -0
- package/dist/monitors-context.js.map +1 -0
- package/dist/monitors-runtime.d.ts +36 -0
- package/dist/monitors-runtime.d.ts.map +1 -0
- package/dist/monitors-runtime.js +103 -0
- package/dist/monitors-runtime.js.map +1 -0
- package/dist/monitors-service.d.ts +71 -0
- package/dist/monitors-service.d.ts.map +1 -0
- package/dist/monitors-service.js +1665 -0
- package/dist/monitors-service.js.map +1 -0
- package/dist/monitors-store.d.ts +83 -0
- package/dist/monitors-store.d.ts.map +1 -0
- package/dist/monitors-store.js +283 -0
- package/dist/monitors-store.js.map +1 -0
- package/dist/process-jobs-context.d.ts +8 -0
- package/dist/process-jobs-context.d.ts.map +1 -1
- package/dist/process-jobs-context.js +11 -0
- package/dist/process-jobs-context.js.map +1 -1
- package/dist/process-jobs-protection.js +1 -1
- package/dist/process-jobs-protection.js.map +1 -1
- package/dist/process-jobs-runtime.d.ts.map +1 -1
- package/dist/process-jobs-runtime.js +1 -12
- package/dist/process-jobs-runtime.js.map +1 -1
- package/dist/process-jobs-service.d.ts.map +1 -1
- package/dist/process-jobs-service.js +3 -149
- package/dist/process-jobs-service.js.map +1 -1
- package/dist/process-output-redaction.d.ts +33 -0
- package/dist/process-output-redaction.d.ts.map +1 -0
- package/dist/process-output-redaction.js +149 -0
- package/dist/process-output-redaction.js.map +1 -0
- package/dist/provider-model-catalog.d.ts +78 -0
- package/dist/provider-model-catalog.d.ts.map +1 -0
- package/dist/provider-model-catalog.js +439 -0
- package/dist/provider-model-catalog.js.map +1 -0
- package/dist/provider-setup.d.ts +4 -13
- package/dist/provider-setup.d.ts.map +1 -1
- package/dist/provider-setup.js +5 -115
- package/dist/provider-setup.js.map +1 -1
- package/dist/readiness-probe-worker.d.ts +1 -2
- package/dist/readiness-probe-worker.d.ts.map +1 -1
- package/dist/readiness-probe-worker.js +3 -8
- package/dist/readiness-probe-worker.js.map +1 -1
- package/dist/readiness-probe.d.ts +1 -1
- package/dist/readiness-probe.d.ts.map +1 -1
- package/dist/readiness-probe.js +3 -33
- package/dist/readiness-probe.js.map +1 -1
- package/dist/request-model-override.d.ts +4 -36
- package/dist/request-model-override.d.ts.map +1 -1
- package/dist/request-model-override.js +58 -146
- package/dist/request-model-override.js.map +1 -1
- package/dist/runtime-option-extensions.d.ts +2 -4
- package/dist/runtime-option-extensions.d.ts.map +1 -1
- package/dist/runtime-option-extensions.js +4 -8
- package/dist/runtime-option-extensions.js.map +1 -1
- package/dist/runtime-routes.d.ts +5 -5
- package/dist/runtime-routes.d.ts.map +1 -1
- package/dist/runtime-routes.js +29 -18
- package/dist/runtime-routes.js.map +1 -1
- package/dist/sandbox-settings-cleanup.d.ts +15 -0
- package/dist/sandbox-settings-cleanup.d.ts.map +1 -0
- package/dist/sandbox-settings-cleanup.js +88 -0
- package/dist/sandbox-settings-cleanup.js.map +1 -0
- package/dist/trigger-overrides.d.ts +6 -0
- package/dist/trigger-overrides.d.ts.map +1 -1
- package/dist/trigger-overrides.js +36 -4
- package/dist/trigger-overrides.js.map +1 -1
- package/dist/untrusted-text.d.ts +36 -0
- package/dist/untrusted-text.d.ts.map +1 -0
- package/dist/untrusted-text.js +150 -0
- package/dist/untrusted-text.js.map +1 -0
- package/dist/wizard/answers.d.ts +3 -9
- package/dist/wizard/answers.d.ts.map +1 -1
- package/dist/wizard/answers.js +11 -36
- package/dist/wizard/answers.js.map +1 -1
- package/dist/wizard/from-flags.d.ts +1 -2
- package/dist/wizard/from-flags.d.ts.map +1 -1
- package/dist/wizard/from-flags.js +8 -3
- package/dist/wizard/from-flags.js.map +1 -1
- package/dist/wizard/model-discovery.d.ts +7 -8
- package/dist/wizard/model-discovery.d.ts.map +1 -1
- package/dist/wizard/model-discovery.js +58 -431
- package/dist/wizard/model-discovery.js.map +1 -1
- package/dist/wizard/presets.js +2 -2
- package/dist/wizard/presets.js.map +1 -1
- package/dist/wizard/prompts.d.ts +13 -12
- package/dist/wizard/prompts.d.ts.map +1 -1
- package/dist/wizard/prompts.js +24 -45
- package/dist/wizard/prompts.js.map +1 -1
- package/dist/wizard/run.d.ts.map +1 -1
- package/dist/wizard/run.js +29 -152
- package/dist/wizard/run.js.map +1 -1
- package/package.json +17 -17
- package/schema/mono-agent.config.schema.json +197 -47
- package/skills/mono-agent-composer/SKILL.md +2 -2
- package/skills/mono-agent-composer/references/config-blueprint.md +45 -40
- package/skills/mono-agent-composer/references/discovery-questions.md +8 -13
- package/skills/mono-agent-composer/references/feature-coverage.md +11 -9
- package/skills/mono-agent-composer/references/package-map.md +22 -16
- package/skills/mono-agent-composer/references/playbooks.md +22 -26
- package/skills/mono-agent-composer/references/validation.md +1 -4
- package/dist/codex-model-catalog.d.ts +0 -15
- package/dist/codex-model-catalog.d.ts.map +0 -1
- package/dist/codex-model-catalog.js +0 -220
- package/dist/codex-model-catalog.js.map +0 -1
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { homedir, tmpdir } from "node:os";
|
|
1
|
+
import { homedir } from "node:os";
|
|
3
2
|
import { join } from "node:path";
|
|
4
3
|
import { getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
5
4
|
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
|
6
|
-
import {
|
|
7
|
-
import { codexModelDiscoveryEnvironment, normalizeEfforts, requestCodexModelList, } from "../codex-model-catalog.js";
|
|
5
|
+
import { EFFORT_LEVELS } from "@mono-agent/config";
|
|
8
6
|
import { inspectPiAuthStore as inspectDefaultPiAuthStore, } from "../pi-auth-store-inspection.js";
|
|
9
|
-
import {
|
|
10
|
-
export { codexModelDiscoveryEnvironment, };
|
|
7
|
+
import { runBoundedProviderCommand } from "../provider-setup.js";
|
|
11
8
|
/** Cloud Pi providers that guided onboarding can authenticate and prove end to end. */
|
|
12
9
|
export const GUIDED_PI_PROVIDER_IDS = [
|
|
13
10
|
"anthropic",
|
|
@@ -17,6 +14,18 @@ export const GUIDED_PI_PROVIDER_IDS = [
|
|
|
17
14
|
];
|
|
18
15
|
const GUIDED_PI_PROVIDERS = new Set(GUIDED_PI_PROVIDER_IDS);
|
|
19
16
|
const GUIDED_LOCAL_PI_PROVIDERS = new Set(["ollama", "lmstudio"]);
|
|
17
|
+
const PI_API_KEY_ENV_BY_PROVIDER = {
|
|
18
|
+
"opencode-go": "OPENCODE_API_KEY",
|
|
19
|
+
};
|
|
20
|
+
/** Whether a selected Pi route has an API key in the destination agent environment. */
|
|
21
|
+
export function hasDurablePiEnvironmentCredential(rawModelRef, persistedEnv) {
|
|
22
|
+
const separator = rawModelRef.indexOf(":");
|
|
23
|
+
if (separator <= 0)
|
|
24
|
+
return false;
|
|
25
|
+
const provider = rawModelRef.slice(0, separator);
|
|
26
|
+
const apiKeyEnv = PI_API_KEY_ENV_BY_PROVIDER[provider];
|
|
27
|
+
return apiKeyEnv !== undefined && (persistedEnv[apiKeyEnv]?.trim().length ?? 0) > 0;
|
|
28
|
+
}
|
|
20
29
|
/** Reject known unsupported remote Pi integrations while leaving custom local ids available. */
|
|
21
30
|
export function guidedPiProviderProblem(provider) {
|
|
22
31
|
if (GUIDED_PI_PROVIDERS.has(provider) || GUIDED_LOCAL_PI_PROVIDERS.has(provider)) {
|
|
@@ -42,52 +51,49 @@ function providerDiscoveryCommand(opts) {
|
|
|
42
51
|
});
|
|
43
52
|
}
|
|
44
53
|
const DEFAULT_DISCOVERY_TIMEOUT_MS = 1200;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
const KNOWN_EFFORTS = new Set(EFFORT_LEVELS);
|
|
55
|
+
function normalizeEfforts(values) {
|
|
56
|
+
return [...new Set(values
|
|
57
|
+
.map((value) => value === "off" ? "none" : value)
|
|
58
|
+
.filter((value) => typeof value === "string" && KNOWN_EFFORTS.has(value)))];
|
|
59
|
+
}
|
|
51
60
|
export const STATIC_MODEL_CANDIDATES = [
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
{
|
|
62
|
+
value: "openai-codex:gpt-5.6-terra",
|
|
63
|
+
label: "Pi OpenAI Codex · GPT-5.6 Terra",
|
|
64
|
+
hint: "OAuth setup available",
|
|
65
|
+
source: "pi",
|
|
66
|
+
availability: "catalog_available",
|
|
67
|
+
authState: "auth_required",
|
|
68
|
+
setupRequired: true,
|
|
69
|
+
supportedEfforts: [],
|
|
70
|
+
providerDefault: true,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
value: "openai-codex:gpt-5.6-sol",
|
|
74
|
+
label: "Pi OpenAI Codex · GPT-5.6 Sol",
|
|
75
|
+
hint: "OAuth setup available",
|
|
76
|
+
source: "pi",
|
|
62
77
|
availability: "catalog_available",
|
|
63
78
|
authState: "auth_required",
|
|
64
|
-
supportedEfforts: efforts,
|
|
65
79
|
setupRequired: true,
|
|
66
|
-
|
|
80
|
+
supportedEfforts: [],
|
|
81
|
+
},
|
|
67
82
|
];
|
|
68
83
|
export async function discoverWizardModelCandidates(opts = {}) {
|
|
69
84
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_DISCOVERY_TIMEOUT_MS;
|
|
70
|
-
const [
|
|
71
|
-
discoverDirectCodex({ ...opts, timeoutMs }),
|
|
85
|
+
const [pi, ollama, lmstudio] = await Promise.all([
|
|
72
86
|
discoverPiModels({ ...opts, timeoutMs }),
|
|
73
|
-
discoverClaudeModels({ ...opts, timeoutMs }),
|
|
74
|
-
discoverOpenCodeModels({
|
|
75
|
-
...opts,
|
|
76
|
-
timeoutMs: opts.timeoutMs ?? DEFAULT_OPENCODE_DISCOVERY_TIMEOUT_MS,
|
|
77
|
-
}),
|
|
78
87
|
discoverOllamaModels({ ...opts, timeoutMs }),
|
|
79
88
|
discoverLmStudioModels({ ...opts, timeoutMs }),
|
|
80
89
|
]);
|
|
81
90
|
return {
|
|
82
91
|
candidates: rankWizardModelCandidates([
|
|
83
|
-
...codex.candidates,
|
|
84
92
|
...pi.candidates,
|
|
85
|
-
...claude.candidates,
|
|
86
|
-
...opencode.candidates,
|
|
87
93
|
...ollama.candidates,
|
|
88
94
|
...lmstudio.candidates,
|
|
89
95
|
]),
|
|
90
|
-
statuses: [
|
|
96
|
+
statuses: [pi.status, ollama.status, lmstudio.status],
|
|
91
97
|
};
|
|
92
98
|
}
|
|
93
99
|
export function rankWizardModelCandidates(candidates) {
|
|
@@ -108,88 +114,16 @@ export function defaultEffortForModelRef(modelRef, reasoning) {
|
|
|
108
114
|
if (reasoning === false) {
|
|
109
115
|
return "none";
|
|
110
116
|
}
|
|
111
|
-
|
|
117
|
+
const separator = modelRef.indexOf(":");
|
|
118
|
+
if (separator <= 0 || separator === modelRef.length - 1)
|
|
112
119
|
return undefined;
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const model = modelParts.join(":");
|
|
120
|
+
const provider = modelRef.slice(0, separator);
|
|
121
|
+
const model = modelRef.slice(separator + 1);
|
|
116
122
|
if (provider === "opencode-go" || provider === "ollama" || provider === "lmstudio") {
|
|
117
123
|
return localModelDefaultEffort(model);
|
|
118
124
|
}
|
|
119
125
|
return undefined;
|
|
120
126
|
}
|
|
121
|
-
/** Detect the direct Codex CLI and its account catalog without claiming readiness. */
|
|
122
|
-
async function discoverDirectCodex(opts) {
|
|
123
|
-
const run = providerDiscoveryCommand(opts);
|
|
124
|
-
const verified = new Set(opts.verifiedModelRefs ?? []);
|
|
125
|
-
let version = "";
|
|
126
|
-
try {
|
|
127
|
-
const result = await run("codex", ["--version"], { timeout: opts.timeoutMs });
|
|
128
|
-
version = firstOutputLine(result.stdout);
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
return {
|
|
132
|
-
candidates: directCodexCandidates(curatedCodexCatalog(), "install-required", "", verified),
|
|
133
|
-
status: {
|
|
134
|
-
provider: "Codex",
|
|
135
|
-
status: "setup_available",
|
|
136
|
-
detail: "CLI not found; install Codex and sign in before the readiness check",
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
let catalog = curatedCodexCatalog();
|
|
141
|
-
try {
|
|
142
|
-
// Injected command runners are normally deterministic unit-test seams; do
|
|
143
|
-
// not escape them by starting a real app-server unless a model-list seam
|
|
144
|
-
// was also supplied.
|
|
145
|
-
const discoveredCatalog = opts.codexModelList !== undefined
|
|
146
|
-
? [...await opts.codexModelList()]
|
|
147
|
-
: opts.execFile === undefined
|
|
148
|
-
? await requestCodexModelList(opts.timeoutMs, codexModelDiscoveryEnvironment(opts.persistedEnv), opts.abortSignal)
|
|
149
|
-
: catalog;
|
|
150
|
-
if (discoveredCatalog.length > 0)
|
|
151
|
-
catalog = discoveredCatalog;
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
// The exact curated Sol/Terra fallback remains selectable offline.
|
|
155
|
-
}
|
|
156
|
-
const durableCredential = hasDurableProviderEnvironmentCredential("codex:gpt-5.6-terra", opts.persistedEnv ?? {});
|
|
157
|
-
const shellOnlyCredential = !durableCredential
|
|
158
|
-
&& hasDurableProviderEnvironmentCredential("codex:gpt-5.6-terra", process.env);
|
|
159
|
-
try {
|
|
160
|
-
if (!durableCredential) {
|
|
161
|
-
await run("codex", ["login", "status"], {
|
|
162
|
-
timeout: opts.timeoutMs,
|
|
163
|
-
env: credentialNeutralProviderStatusEnvironment(process.env, opts.persistedEnv),
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
const candidates = directCodexCandidates(catalog, "credential-detected", version, verified);
|
|
167
|
-
const setupModels = candidates.filter((candidate) => candidate.setupRequired === true);
|
|
168
|
-
const setupDetails = [...new Set(setupModels.map((candidate) => candidate.hint ?? `${candidate.label} setup required`))];
|
|
169
|
-
return {
|
|
170
|
-
candidates,
|
|
171
|
-
status: {
|
|
172
|
-
provider: "Codex",
|
|
173
|
-
status: setupModels.length === 0 ? "detected" : "setup_available",
|
|
174
|
-
detail: `${version.length > 0 ? `${version}; ` : ""}${durableCredential ? "durable OPENAI_API_KEY detected" : "sign-in detected"} (live readiness not yet verified)${setupModels.length === 0
|
|
175
|
-
? ""
|
|
176
|
-
: `; ${setupDetails.join("; ")}`}`,
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
catch {
|
|
181
|
-
return {
|
|
182
|
-
candidates: directCodexCandidates(catalog, "login-required", version, verified),
|
|
183
|
-
status: {
|
|
184
|
-
provider: "Codex",
|
|
185
|
-
status: "setup_available",
|
|
186
|
-
detail: `${version.length > 0 ? `${version}; ` : "CLI installed; "}${shellOnlyCredential
|
|
187
|
-
? "durable sign-in required; shell-only OPENAI_API_KEY ignored"
|
|
188
|
-
: "sign-in required"}`,
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
127
|
async function discoverPiModels(opts) {
|
|
194
128
|
const inspectAuthStore = opts.inspectPiAuthStore ?? inspectDefaultPiAuthStore;
|
|
195
129
|
const authPath = opts.piAuthPath ?? join(homedir(), ".pi", "agent", "auth.json");
|
|
@@ -226,7 +160,7 @@ async function discoverPiModels(opts) {
|
|
|
226
160
|
}
|
|
227
161
|
const preEnvironmentStatus = status;
|
|
228
162
|
for (const provider of GUIDED_PI_PROVIDER_IDS) {
|
|
229
|
-
if (
|
|
163
|
+
if (hasDurablePiEnvironmentCredential(`${provider}:credential-check`, opts.persistedEnv ?? {})) {
|
|
230
164
|
credentialProviders.add(provider);
|
|
231
165
|
}
|
|
232
166
|
}
|
|
@@ -238,7 +172,7 @@ async function discoverPiModels(opts) {
|
|
|
238
172
|
};
|
|
239
173
|
}
|
|
240
174
|
else if (credentialProviders.size === 0
|
|
241
|
-
&&
|
|
175
|
+
&& hasDurablePiEnvironmentCredential("opencode-go:credential-check", process.env)) {
|
|
242
176
|
status = {
|
|
243
177
|
provider: "Pi",
|
|
244
178
|
status: "setup_available",
|
|
@@ -254,7 +188,7 @@ async function discoverPiModels(opts) {
|
|
|
254
188
|
const candidates = models.getModels()
|
|
255
189
|
.filter((model) => GUIDED_PI_PROVIDERS.has(model.provider))
|
|
256
190
|
.map((model) => {
|
|
257
|
-
const value =
|
|
191
|
+
const value = `${model.provider}:${model.id}`;
|
|
258
192
|
const supportedEfforts = normalizeEfforts(getSupportedThinkingLevels(model));
|
|
259
193
|
const authState = verified.has(value)
|
|
260
194
|
? "verified"
|
|
@@ -263,7 +197,7 @@ async function discoverPiModels(opts) {
|
|
|
263
197
|
: "auth_required";
|
|
264
198
|
const defaultEffort = exactDefaultEffortWhenUnambiguous(supportedEfforts);
|
|
265
199
|
const shellOnlyCredential = authState === "auth_required"
|
|
266
|
-
&&
|
|
200
|
+
&& hasDurablePiEnvironmentCredential(value, process.env);
|
|
267
201
|
const providerLabel = model.provider === "opencode-go"
|
|
268
202
|
? "OpenCode-Go"
|
|
269
203
|
: providerNames.get(model.provider) ?? model.provider;
|
|
@@ -309,174 +243,6 @@ function isCredentialString(value) {
|
|
|
309
243
|
&& value.length <= 65_536
|
|
310
244
|
&& !value.includes("\0");
|
|
311
245
|
}
|
|
312
|
-
async function discoverClaudeModels(opts) {
|
|
313
|
-
const run = providerDiscoveryCommand(opts);
|
|
314
|
-
const verified = new Set(opts.verifiedModelRefs ?? []);
|
|
315
|
-
let credentialDetected = hasDurableProviderEnvironmentCredential("claude:claude-sonnet-5", opts.persistedEnv ?? {});
|
|
316
|
-
const durableCredential = credentialDetected;
|
|
317
|
-
const shellOnlyCredential = !durableCredential
|
|
318
|
-
&& hasDurableProviderEnvironmentCredential("claude:claude-sonnet-5", process.env);
|
|
319
|
-
if (!credentialDetected) {
|
|
320
|
-
try {
|
|
321
|
-
await run("claude", ["auth", "status", "--json"], {
|
|
322
|
-
timeout: opts.timeoutMs,
|
|
323
|
-
env: credentialNeutralProviderStatusEnvironment(process.env, opts.persistedEnv),
|
|
324
|
-
});
|
|
325
|
-
credentialDetected = true;
|
|
326
|
-
}
|
|
327
|
-
catch {
|
|
328
|
-
// Catalog discovery is deliberately independent from account state.
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
let catalog = [];
|
|
332
|
-
try {
|
|
333
|
-
catalog = opts.claudeModelList !== undefined
|
|
334
|
-
? await opts.claudeModelList()
|
|
335
|
-
: opts.execFile === undefined
|
|
336
|
-
? await discoverClaudeSdkModels({ timeoutMs: Math.max(opts.timeoutMs, 2_000) })
|
|
337
|
-
: await discoverClaudeSdkModels({ timeoutMs: 1 });
|
|
338
|
-
}
|
|
339
|
-
catch {
|
|
340
|
-
// Static SDK-versioned rows remain available through STATIC_MODEL_CANDIDATES.
|
|
341
|
-
}
|
|
342
|
-
const candidates = catalog.map((model) => {
|
|
343
|
-
const value = model.reference;
|
|
344
|
-
const authState = verified.has(value)
|
|
345
|
-
? "verified"
|
|
346
|
-
: credentialDetected
|
|
347
|
-
? "credential_detected"
|
|
348
|
-
: "auth_required";
|
|
349
|
-
const supportedEfforts = normalizeEfforts(model.supportedEfforts);
|
|
350
|
-
return {
|
|
351
|
-
value,
|
|
352
|
-
label: model.displayName,
|
|
353
|
-
hint: `${model.source === "discovered" ? "discovered from Claude SDK" : "SDK-versioned cached catalog"}; ${authState === "verified" ? "verified" : authState === "credential_detected" ? "credential detected; live readiness pending" : "sign-in required"}`,
|
|
354
|
-
source: "claude",
|
|
355
|
-
availability: "catalog_available",
|
|
356
|
-
authState,
|
|
357
|
-
supportedEfforts,
|
|
358
|
-
...(authState === "verified" ? { discovered: true } : {}),
|
|
359
|
-
...(authState === "auth_required" ? { setupRequired: true } : {}),
|
|
360
|
-
};
|
|
361
|
-
});
|
|
362
|
-
return {
|
|
363
|
-
candidates,
|
|
364
|
-
status: credentialDetected
|
|
365
|
-
? {
|
|
366
|
-
provider: "Claude",
|
|
367
|
-
status: "detected",
|
|
368
|
-
detail: `${durableCredential ? "durable provider credential" : "sign-in"} detected (live readiness not yet verified)`,
|
|
369
|
-
}
|
|
370
|
-
: {
|
|
371
|
-
provider: "Claude",
|
|
372
|
-
status: "setup_available",
|
|
373
|
-
detail: `${shellOnlyCredential
|
|
374
|
-
? "durable sign-in required; shell-only Claude credential ignored"
|
|
375
|
-
: "sign-in required"}; catalog remains available`,
|
|
376
|
-
},
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
async function discoverOpenCodeModels(opts) {
|
|
380
|
-
const run = providerDiscoveryCommand(opts);
|
|
381
|
-
let isolation;
|
|
382
|
-
try {
|
|
383
|
-
isolation = await createOpenCodeDiscoveryIsolation();
|
|
384
|
-
const { stdout } = await run("opencode", ["models", "opencode-go", "--pure"], {
|
|
385
|
-
timeout: opts.timeoutMs,
|
|
386
|
-
env: isolation.env,
|
|
387
|
-
});
|
|
388
|
-
const bundledModelIds = new Set(builtinModels().getModels()
|
|
389
|
-
.filter((model) => model.provider === "opencode-go")
|
|
390
|
-
.map((model) => model.id));
|
|
391
|
-
const parsedModels = parseOpenCodeGoModels(stdout);
|
|
392
|
-
const models = parsedModels.filter((model) => bundledModelIds.has(model));
|
|
393
|
-
const unsupportedCount = parsedModels.length - models.length;
|
|
394
|
-
return {
|
|
395
|
-
candidates: models.map((model) => {
|
|
396
|
-
const value = `pi:opencode-go:${model}`;
|
|
397
|
-
return {
|
|
398
|
-
value,
|
|
399
|
-
label: `OpenCode-Go ${displayModelName(model)}`,
|
|
400
|
-
hint: "discovered from opencode; OpenCode-Go API key required",
|
|
401
|
-
source: "opencode",
|
|
402
|
-
discovered: true,
|
|
403
|
-
availability: "catalog_available",
|
|
404
|
-
authState: "auth_required",
|
|
405
|
-
setupRequired: true,
|
|
406
|
-
supportedEfforts: [],
|
|
407
|
-
};
|
|
408
|
-
}),
|
|
409
|
-
status: models.length > 0
|
|
410
|
-
? {
|
|
411
|
-
provider: "OpenCode-Go",
|
|
412
|
-
status: "detected",
|
|
413
|
-
detail: `${models.length} runtime-supported model${models.length === 1 ? "" : "s"} found${unsupportedCount === 0
|
|
414
|
-
? ""
|
|
415
|
-
: `; ${unsupportedCount} unsupported CLI row${unsupportedCount === 1 ? "" : "s"} ignored`}`,
|
|
416
|
-
}
|
|
417
|
-
: parsedModels.length > 0
|
|
418
|
-
? {
|
|
419
|
-
provider: "OpenCode-Go",
|
|
420
|
-
status: "unavailable",
|
|
421
|
-
detail: `no runtime-supported models; ${parsedModels.length} unsupported CLI row${parsedModels.length === 1 ? "" : "s"} ignored`,
|
|
422
|
-
}
|
|
423
|
-
: { provider: "OpenCode-Go", status: "unavailable", detail: "no models returned" },
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
catch {
|
|
427
|
-
return { candidates: [], status: { provider: "OpenCode-Go", status: "unavailable", detail: "`opencode models opencode-go --pure` unavailable" } };
|
|
428
|
-
}
|
|
429
|
-
finally {
|
|
430
|
-
await isolation?.cleanup();
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
async function createOpenCodeDiscoveryIsolation() {
|
|
434
|
-
const root = await mkdtemp(join(tmpdir(), "mono-agent-opencode-discovery-"));
|
|
435
|
-
try {
|
|
436
|
-
await chmod(root, 0o700);
|
|
437
|
-
const home = await createPrivateDirectory(root, "home");
|
|
438
|
-
const config = await createPrivateDirectory(root, "config");
|
|
439
|
-
const opencodeConfig = await createPrivateDirectory(config, "opencode");
|
|
440
|
-
if (process.platform !== "win32")
|
|
441
|
-
await chmod(opencodeConfig, 0o500);
|
|
442
|
-
const data = await createPrivateDirectory(root, "data");
|
|
443
|
-
const state = await createPrivateDirectory(root, "state");
|
|
444
|
-
const cache = await createPrivateDirectory(root, "cache");
|
|
445
|
-
const opencodeData = await createPrivateDirectory(data, "opencode");
|
|
446
|
-
const database = join(opencodeData, "opencode.db");
|
|
447
|
-
const handle = await open(database, "wx", 0o600);
|
|
448
|
-
await handle.close();
|
|
449
|
-
await chmod(database, 0o600);
|
|
450
|
-
const env = safeDiscoveryProcessEnv();
|
|
451
|
-
Object.assign(env, {
|
|
452
|
-
OPENCODE_TEST_HOME: home,
|
|
453
|
-
XDG_CONFIG_HOME: config,
|
|
454
|
-
XDG_CONFIG_DIRS: config,
|
|
455
|
-
XDG_DATA_HOME: data,
|
|
456
|
-
XDG_DATA_DIRS: data,
|
|
457
|
-
XDG_STATE_HOME: state,
|
|
458
|
-
XDG_CACHE_HOME: cache,
|
|
459
|
-
OPENCODE_DB: database,
|
|
460
|
-
OPENCODE_CONFIG_CONTENT: JSON.stringify({ share: "disabled", autoshare: false }),
|
|
461
|
-
OPENCODE_DISABLE_PROJECT_CONFIG: "true",
|
|
462
|
-
OPENCODE_DISABLE_AUTOUPDATE: "true",
|
|
463
|
-
OPENCODE_DISABLE_SHARE: "true",
|
|
464
|
-
OPENCODE_AUTO_SHARE: "false",
|
|
465
|
-
OPENCODE_DISABLE_EXTERNAL_SKILLS: "true",
|
|
466
|
-
OPENCODE_DISABLE_LSP_DOWNLOAD: "true",
|
|
467
|
-
});
|
|
468
|
-
return {
|
|
469
|
-
env,
|
|
470
|
-
cleanup: async () => {
|
|
471
|
-
await rm(root, { recursive: true, force: true }).catch(() => undefined);
|
|
472
|
-
},
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
catch (error) {
|
|
476
|
-
await rm(root, { recursive: true, force: true }).catch(() => undefined);
|
|
477
|
-
throw error;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
246
|
function safeDiscoveryProcessEnv(source = process.env) {
|
|
481
247
|
const env = {};
|
|
482
248
|
for (const key of [
|
|
@@ -499,12 +265,6 @@ function safeDiscoveryProcessEnv(source = process.env) {
|
|
|
499
265
|
}
|
|
500
266
|
return env;
|
|
501
267
|
}
|
|
502
|
-
async function createPrivateDirectory(parent, name) {
|
|
503
|
-
const path = join(parent, name);
|
|
504
|
-
await mkdir(path, { mode: 0o700 });
|
|
505
|
-
await chmod(path, 0o700);
|
|
506
|
-
return path;
|
|
507
|
-
}
|
|
508
268
|
async function discoverOllamaModels(opts) {
|
|
509
269
|
const run = providerDiscoveryCommand(opts);
|
|
510
270
|
try {
|
|
@@ -512,7 +272,7 @@ async function discoverOllamaModels(opts) {
|
|
|
512
272
|
const models = parseOllamaList(stdout);
|
|
513
273
|
return {
|
|
514
274
|
candidates: models.map((model) => {
|
|
515
|
-
const value = `
|
|
275
|
+
const value = `ollama:${model}`;
|
|
516
276
|
return {
|
|
517
277
|
value,
|
|
518
278
|
label: `Ollama ${model}`,
|
|
@@ -548,7 +308,7 @@ async function discoverLmStudioModels(opts) {
|
|
|
548
308
|
const models = parseOpenAiModelEntriesBody(body);
|
|
549
309
|
return {
|
|
550
310
|
candidates: models.map((model) => {
|
|
551
|
-
const value = `
|
|
311
|
+
const value = `lmstudio:${model.id}`;
|
|
552
312
|
return {
|
|
553
313
|
value,
|
|
554
314
|
label: `LM Studio ${model.id}`,
|
|
@@ -582,7 +342,7 @@ function mergeCandidate(left, right) {
|
|
|
582
342
|
|| right.availability !== undefined
|
|
583
343
|
|| right.authState !== undefined;
|
|
584
344
|
const preserveBuiltinPiMetadata = left.source === "pi"
|
|
585
|
-
&& (right.source === "
|
|
345
|
+
&& (right.source === "ollama" || right.source === "lmstudio");
|
|
586
346
|
const hint = preserveBuiltinPiMetadata
|
|
587
347
|
? left.hint
|
|
588
348
|
: rightHasDiscoveryState ? right.hint ?? left.hint : left.hint ?? right.hint;
|
|
@@ -626,18 +386,12 @@ function rank(candidate) {
|
|
|
626
386
|
function modelRank(candidate) {
|
|
627
387
|
if (candidate.providerDefault === true)
|
|
628
388
|
return -100;
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
if (
|
|
634
|
-
return 10 + piOpenAiCodexRank;
|
|
635
|
-
if (candidate.source === "claude") {
|
|
389
|
+
if (candidate.value === "openai-codex:gpt-5.6-terra")
|
|
390
|
+
return 0;
|
|
391
|
+
if (candidate.value === "openai-codex:gpt-5.6-sol")
|
|
392
|
+
return 1;
|
|
393
|
+
if (candidate.source === "pi")
|
|
636
394
|
return 20;
|
|
637
|
-
}
|
|
638
|
-
if (candidate.source === "opencode") {
|
|
639
|
-
return 30;
|
|
640
|
-
}
|
|
641
395
|
if (candidate.source === "ollama") {
|
|
642
396
|
return candidate.discovered === true ? 40 : 45;
|
|
643
397
|
}
|
|
@@ -646,103 +400,6 @@ function modelRank(candidate) {
|
|
|
646
400
|
}
|
|
647
401
|
return 90;
|
|
648
402
|
}
|
|
649
|
-
function directCodexRef(model) {
|
|
650
|
-
return `codex:${model.id}`;
|
|
651
|
-
}
|
|
652
|
-
function piOpenAiCodexRef(model) {
|
|
653
|
-
return `pi:${PI_OPENAI_CODEX_PROVIDER}:${model.id}`;
|
|
654
|
-
}
|
|
655
|
-
function staticDirectCodexCandidate(model) {
|
|
656
|
-
return {
|
|
657
|
-
value: directCodexRef(model),
|
|
658
|
-
label: `Codex ${model.name}`,
|
|
659
|
-
...(model.minimumCodexCliVersion === undefined
|
|
660
|
-
? {}
|
|
661
|
-
: { hint: `requires Codex CLI ${formatVersion(model.minimumCodexCliVersion)}+` }),
|
|
662
|
-
source: "codex",
|
|
663
|
-
availability: "catalog_available",
|
|
664
|
-
authState: "auth_required",
|
|
665
|
-
// Exact effort support/defaults come from Codex app-server model/list.
|
|
666
|
-
// Do not fabricate provider metadata when the live catalog is unavailable.
|
|
667
|
-
supportedEfforts: [],
|
|
668
|
-
providerDefault: model.id === "gpt-5.6-terra",
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
function directCodexCandidates(catalog, state, version = "", verified = new Set()) {
|
|
672
|
-
return catalog.map((model) => directCodexCandidate(model, state, version, verified));
|
|
673
|
-
}
|
|
674
|
-
function directCodexCandidate(model, state, version = "", verified = new Set()) {
|
|
675
|
-
const reference = `codex:${model.id}`;
|
|
676
|
-
const curated = OPENAI_CODEX_MODELS.find((entry) => entry.id === model.id);
|
|
677
|
-
const authState = verified.has(reference)
|
|
678
|
-
? "verified"
|
|
679
|
-
: state === "credential-detected"
|
|
680
|
-
? "credential_detected"
|
|
681
|
-
: "auth_required";
|
|
682
|
-
if (state === "install-required") {
|
|
683
|
-
const minimum = curated?.minimumCodexCliVersion;
|
|
684
|
-
return {
|
|
685
|
-
value: reference,
|
|
686
|
-
label: `Codex ${model.displayName}`,
|
|
687
|
-
hint: minimum === undefined
|
|
688
|
-
? "install Codex CLI and sign in"
|
|
689
|
-
: `install Codex CLI ${formatVersion(minimum)}+ and sign in`,
|
|
690
|
-
source: "codex",
|
|
691
|
-
setupRequired: true,
|
|
692
|
-
availability: "catalog_available",
|
|
693
|
-
authState,
|
|
694
|
-
supportedEfforts: model.supportedEfforts,
|
|
695
|
-
...(model.isDefault === undefined ? {} : { providerDefault: model.isDefault }),
|
|
696
|
-
...(model.defaultEffort === undefined ? {} : { defaultEffort: model.defaultEffort }),
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
const prerequisites = [];
|
|
700
|
-
const minimum = curated?.minimumCodexCliVersion;
|
|
701
|
-
if (minimum !== undefined && !codexVersionMeetsMinimum(version, minimum)) {
|
|
702
|
-
prerequisites.push(parseCodexVersion(version) === undefined
|
|
703
|
-
? `Codex CLI ${formatVersion(minimum)}+ required; installed version could not be verified`
|
|
704
|
-
: `update Codex CLI to ${formatVersion(minimum)}+ (found ${version})`);
|
|
705
|
-
}
|
|
706
|
-
if (state === "login-required")
|
|
707
|
-
prerequisites.push("Codex sign-in required");
|
|
708
|
-
if (prerequisites.length === 0) {
|
|
709
|
-
return {
|
|
710
|
-
value: reference,
|
|
711
|
-
label: `Codex ${model.displayName}`,
|
|
712
|
-
hint: authState === "verified"
|
|
713
|
-
? `${version.length > 0 ? `${version}; ` : ""}verified by live readiness`
|
|
714
|
-
: `${version.length > 0 ? `${version}; ` : ""}sign-in detected; live readiness pending`,
|
|
715
|
-
source: "codex",
|
|
716
|
-
discovered: true,
|
|
717
|
-
availability: "catalog_available",
|
|
718
|
-
authState,
|
|
719
|
-
supportedEfforts: model.supportedEfforts,
|
|
720
|
-
...(model.isDefault === undefined ? {} : { providerDefault: model.isDefault }),
|
|
721
|
-
...(model.defaultEffort === undefined ? {} : { defaultEffort: model.defaultEffort }),
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
return {
|
|
725
|
-
value: reference,
|
|
726
|
-
label: `Codex ${model.displayName}`,
|
|
727
|
-
hint: prerequisites.join("; "),
|
|
728
|
-
source: "codex",
|
|
729
|
-
setupRequired: true,
|
|
730
|
-
availability: "catalog_available",
|
|
731
|
-
authState,
|
|
732
|
-
supportedEfforts: model.supportedEfforts,
|
|
733
|
-
...(model.isDefault === undefined ? {} : { providerDefault: model.isDefault }),
|
|
734
|
-
...(model.defaultEffort === undefined ? {} : { defaultEffort: model.defaultEffort }),
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
function curatedCodexCatalog() {
|
|
738
|
-
return OPENAI_CODEX_MODELS.map((model) => ({
|
|
739
|
-
id: model.id,
|
|
740
|
-
displayName: model.name,
|
|
741
|
-
supportedEfforts: [],
|
|
742
|
-
// Offline product fallback only; live model/list replaces this flag.
|
|
743
|
-
isDefault: model.id === "gpt-5.6-terra",
|
|
744
|
-
}));
|
|
745
|
-
}
|
|
746
403
|
function strongerAuthState(left, right) {
|
|
747
404
|
const order = {
|
|
748
405
|
auth_required: 0,
|
|
@@ -759,30 +416,6 @@ function strongerAuthState(left, right) {
|
|
|
759
416
|
function exactDefaultEffortWhenUnambiguous(supportedEfforts) {
|
|
760
417
|
return supportedEfforts.length === 1 ? supportedEfforts[0] : undefined;
|
|
761
418
|
}
|
|
762
|
-
function parseCodexVersion(version) {
|
|
763
|
-
const match = /(?:^|\s)v?(\d+)\.(\d+)\.(\d+)(?:[-+\s]|$)/u.exec(version);
|
|
764
|
-
if (match === null)
|
|
765
|
-
return undefined;
|
|
766
|
-
const parts = match.slice(1, 4).map(Number);
|
|
767
|
-
if (parts.some((part) => !Number.isSafeInteger(part) || part < 0))
|
|
768
|
-
return undefined;
|
|
769
|
-
return [parts[0], parts[1], parts[2]];
|
|
770
|
-
}
|
|
771
|
-
function codexVersionMeetsMinimum(version, minimum) {
|
|
772
|
-
const parsed = parseCodexVersion(version);
|
|
773
|
-
if (parsed === undefined)
|
|
774
|
-
return false;
|
|
775
|
-
for (let index = 0; index < minimum.length; index += 1) {
|
|
776
|
-
const installedPart = parsed[index] ?? 0;
|
|
777
|
-
const minimumPart = minimum[index] ?? 0;
|
|
778
|
-
if (installedPart !== minimumPart)
|
|
779
|
-
return installedPart > minimumPart;
|
|
780
|
-
}
|
|
781
|
-
return true;
|
|
782
|
-
}
|
|
783
|
-
function formatVersion(version) {
|
|
784
|
-
return version.join(".");
|
|
785
|
-
}
|
|
786
419
|
function parseOllamaList(stdout) {
|
|
787
420
|
const lines = stdout.trim().split(/\r?\n/u).filter(Boolean);
|
|
788
421
|
if (lines.length === 0) {
|
|
@@ -793,7 +426,7 @@ function parseOllamaList(stdout) {
|
|
|
793
426
|
.map((line) => line.trim().split(/\s+/u)[0])
|
|
794
427
|
.filter((name) => name !== undefined && name.length > 0);
|
|
795
428
|
}
|
|
796
|
-
function parseOpenCodeGoModels(stdout) {
|
|
429
|
+
export function parseOpenCodeGoModels(stdout) {
|
|
797
430
|
const prefix = "opencode-go/";
|
|
798
431
|
return stdout
|
|
799
432
|
.split(/\r?\n/u)
|
|
@@ -824,9 +457,6 @@ function modelEntryFromUnknown(value) {
|
|
|
824
457
|
...(reasoning === undefined ? {} : { reasoning }),
|
|
825
458
|
};
|
|
826
459
|
}
|
|
827
|
-
function displayModelName(model) {
|
|
828
|
-
return model.startsWith("pi:") ? model.split(":").slice(2).join(":") : model;
|
|
829
|
-
}
|
|
830
460
|
function parseJsonObject(value) {
|
|
831
461
|
const parsed = typeof value === "string" ? JSON.parse(value) : value;
|
|
832
462
|
if (!isRecord(parsed)) {
|
|
@@ -834,9 +464,6 @@ function parseJsonObject(value) {
|
|
|
834
464
|
}
|
|
835
465
|
return parsed;
|
|
836
466
|
}
|
|
837
|
-
function firstOutputLine(value) {
|
|
838
|
-
return value.split(/\r?\n/u).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 120) ?? "";
|
|
839
|
-
}
|
|
840
467
|
function readReasoningCapability(value) {
|
|
841
468
|
for (const field of ["reasoning", "supportsReasoning", "supports_reasoning", "thinking", "supportsThinking", "supports_thinking"]) {
|
|
842
469
|
const result = booleanCapability(value[field]);
|