@mono-agent/agent-app 0.20.11 → 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.
Files changed (220) hide show
  1. package/README.md +33 -18
  2. package/dist/app-controller-channels.d.ts +4 -0
  3. package/dist/app-controller-channels.d.ts.map +1 -1
  4. package/dist/app-controller-channels.js +20 -2
  5. package/dist/app-controller-channels.js.map +1 -1
  6. package/dist/app-controller-continuation.d.ts.map +1 -1
  7. package/dist/app-controller-continuation.js +2 -3
  8. package/dist/app-controller-continuation.js.map +1 -1
  9. package/dist/app-controller-lifecycle.d.ts +4 -0
  10. package/dist/app-controller-lifecycle.d.ts.map +1 -1
  11. package/dist/app-controller-lifecycle.js +7 -0
  12. package/dist/app-controller-lifecycle.js.map +1 -1
  13. package/dist/app-controller-monitors.d.ts +26 -0
  14. package/dist/app-controller-monitors.d.ts.map +1 -0
  15. package/dist/app-controller-monitors.js +127 -0
  16. package/dist/app-controller-monitors.js.map +1 -0
  17. package/dist/app-controller-responder.d.ts +7 -17
  18. package/dist/app-controller-responder.d.ts.map +1 -1
  19. package/dist/app-controller-responder.js +33 -69
  20. package/dist/app-controller-responder.js.map +1 -1
  21. package/dist/app-controller-utils.d.ts +1 -5
  22. package/dist/app-controller-utils.d.ts.map +1 -1
  23. package/dist/app-controller-utils.js +4 -21
  24. package/dist/app-controller-utils.js.map +1 -1
  25. package/dist/app-controller.d.ts +24 -10
  26. package/dist/app-controller.d.ts.map +1 -1
  27. package/dist/app-controller.js +36 -1
  28. package/dist/app-controller.js.map +1 -1
  29. package/dist/channel-drivers/slack.d.ts.map +1 -1
  30. package/dist/channel-drivers/slack.js +18 -0
  31. package/dist/channel-drivers/slack.js.map +1 -1
  32. package/dist/channel-drivers/telegram.d.ts.map +1 -1
  33. package/dist/channel-drivers/telegram.js +26 -0
  34. package/dist/channel-drivers/telegram.js.map +1 -1
  35. package/dist/channel-drivers/tui.d.ts +68 -8
  36. package/dist/channel-drivers/tui.d.ts.map +1 -1
  37. package/dist/channel-drivers/tui.js +388 -89
  38. package/dist/channel-drivers/tui.js.map +1 -1
  39. package/dist/channel-runtime-controls.d.ts +2 -1
  40. package/dist/channel-runtime-controls.d.ts.map +1 -1
  41. package/dist/channel-runtime-controls.js +79 -22
  42. package/dist/channel-runtime-controls.js.map +1 -1
  43. package/dist/cli-args.d.ts +4 -6
  44. package/dist/cli-args.d.ts.map +1 -1
  45. package/dist/cli-args.js +16 -36
  46. package/dist/cli-args.js.map +1 -1
  47. package/dist/cli-commands.d.ts.map +1 -1
  48. package/dist/cli-commands.js +11 -0
  49. package/dist/cli-commands.js.map +1 -1
  50. package/dist/cli-help.d.ts +26 -0
  51. package/dist/cli-help.d.ts.map +1 -1
  52. package/dist/cli-help.js +25 -34
  53. package/dist/cli-help.js.map +1 -1
  54. package/dist/cli-init-command.d.ts +1 -2
  55. package/dist/cli-init-command.d.ts.map +1 -1
  56. package/dist/cli-init-command.js +5 -49
  57. package/dist/cli-init-command.js.map +1 -1
  58. package/dist/config-reference.d.ts.map +1 -1
  59. package/dist/config-reference.js +153 -52
  60. package/dist/config-reference.js.map +1 -1
  61. package/dist/configuration-proposal-tool.d.ts.map +1 -1
  62. package/dist/configuration-proposal-tool.js +3 -11
  63. package/dist/configuration-proposal-tool.js.map +1 -1
  64. package/dist/configured-agent.d.ts +18 -3
  65. package/dist/configured-agent.d.ts.map +1 -1
  66. package/dist/configured-agent.js +67 -86
  67. package/dist/configured-agent.js.map +1 -1
  68. package/dist/conversation-title.d.ts.map +1 -1
  69. package/dist/conversation-title.js +9 -2
  70. package/dist/conversation-title.js.map +1 -1
  71. package/dist/doctor.d.ts +7 -13
  72. package/dist/doctor.d.ts.map +1 -1
  73. package/dist/doctor.js +191 -725
  74. package/dist/doctor.js.map +1 -1
  75. package/dist/first-run-readiness.d.ts.map +1 -1
  76. package/dist/first-run-readiness.js +0 -6
  77. package/dist/first-run-readiness.js.map +1 -1
  78. package/dist/local-configuration.d.ts.map +1 -1
  79. package/dist/local-configuration.js +9 -37
  80. package/dist/local-configuration.js.map +1 -1
  81. package/dist/memory-remember.d.ts +49 -0
  82. package/dist/memory-remember.d.ts.map +1 -0
  83. package/dist/memory-remember.js +190 -0
  84. package/dist/memory-remember.js.map +1 -0
  85. package/dist/memory-retrieval.d.ts +24 -0
  86. package/dist/memory-retrieval.d.ts.map +1 -1
  87. package/dist/memory-retrieval.js +23 -0
  88. package/dist/memory-retrieval.js.map +1 -1
  89. package/dist/model-effort-capabilities.d.ts +8 -9
  90. package/dist/model-effort-capabilities.d.ts.map +1 -1
  91. package/dist/model-effort-capabilities.js +17 -35
  92. package/dist/model-effort-capabilities.js.map +1 -1
  93. package/dist/modules/base.d.ts +3 -4
  94. package/dist/modules/base.d.ts.map +1 -1
  95. package/dist/modules/base.js +3 -5
  96. package/dist/modules/base.js.map +1 -1
  97. package/dist/modules/catalog.d.ts.map +1 -1
  98. package/dist/modules/catalog.js +11 -9
  99. package/dist/modules/catalog.js.map +1 -1
  100. package/dist/modules/known-tools.d.ts +2 -2
  101. package/dist/modules/known-tools.d.ts.map +1 -1
  102. package/dist/modules/known-tools.js +6 -0
  103. package/dist/modules/known-tools.js.map +1 -1
  104. package/dist/monitor-channel-routing.d.ts +20 -0
  105. package/dist/monitor-channel-routing.d.ts.map +1 -0
  106. package/dist/monitor-channel-routing.js +73 -0
  107. package/dist/monitor-channel-routing.js.map +1 -0
  108. package/dist/monitors-command.d.ts +23 -0
  109. package/dist/monitors-command.d.ts.map +1 -0
  110. package/dist/monitors-command.js +207 -0
  111. package/dist/monitors-command.js.map +1 -0
  112. package/dist/monitors-config.d.ts +74 -0
  113. package/dist/monitors-config.d.ts.map +1 -0
  114. package/dist/monitors-config.js +146 -0
  115. package/dist/monitors-config.js.map +1 -0
  116. package/dist/monitors-context.d.ts +58 -0
  117. package/dist/monitors-context.d.ts.map +1 -0
  118. package/dist/monitors-context.js +182 -0
  119. package/dist/monitors-context.js.map +1 -0
  120. package/dist/monitors-runtime.d.ts +36 -0
  121. package/dist/monitors-runtime.d.ts.map +1 -0
  122. package/dist/monitors-runtime.js +103 -0
  123. package/dist/monitors-runtime.js.map +1 -0
  124. package/dist/monitors-service.d.ts +71 -0
  125. package/dist/monitors-service.d.ts.map +1 -0
  126. package/dist/monitors-service.js +1665 -0
  127. package/dist/monitors-service.js.map +1 -0
  128. package/dist/monitors-store.d.ts +83 -0
  129. package/dist/monitors-store.d.ts.map +1 -0
  130. package/dist/monitors-store.js +283 -0
  131. package/dist/monitors-store.js.map +1 -0
  132. package/dist/process-jobs-context.d.ts +8 -0
  133. package/dist/process-jobs-context.d.ts.map +1 -1
  134. package/dist/process-jobs-context.js +11 -0
  135. package/dist/process-jobs-context.js.map +1 -1
  136. package/dist/process-jobs-protection.js +1 -1
  137. package/dist/process-jobs-protection.js.map +1 -1
  138. package/dist/process-jobs-runtime.d.ts.map +1 -1
  139. package/dist/process-jobs-runtime.js +1 -12
  140. package/dist/process-jobs-runtime.js.map +1 -1
  141. package/dist/process-jobs-service.d.ts.map +1 -1
  142. package/dist/process-jobs-service.js +3 -149
  143. package/dist/process-jobs-service.js.map +1 -1
  144. package/dist/process-output-redaction.d.ts +33 -0
  145. package/dist/process-output-redaction.d.ts.map +1 -0
  146. package/dist/process-output-redaction.js +149 -0
  147. package/dist/process-output-redaction.js.map +1 -0
  148. package/dist/provider-model-catalog.d.ts +78 -0
  149. package/dist/provider-model-catalog.d.ts.map +1 -0
  150. package/dist/provider-model-catalog.js +439 -0
  151. package/dist/provider-model-catalog.js.map +1 -0
  152. package/dist/provider-setup.d.ts +4 -13
  153. package/dist/provider-setup.d.ts.map +1 -1
  154. package/dist/provider-setup.js +5 -115
  155. package/dist/provider-setup.js.map +1 -1
  156. package/dist/readiness-probe-worker.d.ts +1 -2
  157. package/dist/readiness-probe-worker.d.ts.map +1 -1
  158. package/dist/readiness-probe-worker.js +3 -8
  159. package/dist/readiness-probe-worker.js.map +1 -1
  160. package/dist/readiness-probe.d.ts +1 -1
  161. package/dist/readiness-probe.d.ts.map +1 -1
  162. package/dist/readiness-probe.js +3 -33
  163. package/dist/readiness-probe.js.map +1 -1
  164. package/dist/request-model-override.d.ts +4 -36
  165. package/dist/request-model-override.d.ts.map +1 -1
  166. package/dist/request-model-override.js +58 -146
  167. package/dist/request-model-override.js.map +1 -1
  168. package/dist/runtime-option-extensions.d.ts +2 -4
  169. package/dist/runtime-option-extensions.d.ts.map +1 -1
  170. package/dist/runtime-option-extensions.js +4 -8
  171. package/dist/runtime-option-extensions.js.map +1 -1
  172. package/dist/runtime-routes.d.ts +5 -5
  173. package/dist/runtime-routes.d.ts.map +1 -1
  174. package/dist/runtime-routes.js +29 -18
  175. package/dist/runtime-routes.js.map +1 -1
  176. package/dist/sandbox-settings-cleanup.d.ts +15 -0
  177. package/dist/sandbox-settings-cleanup.d.ts.map +1 -0
  178. package/dist/sandbox-settings-cleanup.js +88 -0
  179. package/dist/sandbox-settings-cleanup.js.map +1 -0
  180. package/dist/trigger-overrides.d.ts +6 -0
  181. package/dist/trigger-overrides.d.ts.map +1 -1
  182. package/dist/trigger-overrides.js +36 -4
  183. package/dist/trigger-overrides.js.map +1 -1
  184. package/dist/untrusted-text.d.ts +36 -0
  185. package/dist/untrusted-text.d.ts.map +1 -0
  186. package/dist/untrusted-text.js +150 -0
  187. package/dist/untrusted-text.js.map +1 -0
  188. package/dist/wizard/answers.d.ts +3 -9
  189. package/dist/wizard/answers.d.ts.map +1 -1
  190. package/dist/wizard/answers.js +11 -36
  191. package/dist/wizard/answers.js.map +1 -1
  192. package/dist/wizard/from-flags.d.ts +1 -2
  193. package/dist/wizard/from-flags.d.ts.map +1 -1
  194. package/dist/wizard/from-flags.js +8 -3
  195. package/dist/wizard/from-flags.js.map +1 -1
  196. package/dist/wizard/model-discovery.d.ts +7 -8
  197. package/dist/wizard/model-discovery.d.ts.map +1 -1
  198. package/dist/wizard/model-discovery.js +58 -431
  199. package/dist/wizard/model-discovery.js.map +1 -1
  200. package/dist/wizard/presets.js +2 -2
  201. package/dist/wizard/presets.js.map +1 -1
  202. package/dist/wizard/prompts.d.ts +13 -12
  203. package/dist/wizard/prompts.d.ts.map +1 -1
  204. package/dist/wizard/prompts.js +24 -45
  205. package/dist/wizard/prompts.js.map +1 -1
  206. package/dist/wizard/run.d.ts.map +1 -1
  207. package/dist/wizard/run.js +29 -152
  208. package/dist/wizard/run.js.map +1 -1
  209. package/package.json +17 -17
  210. package/schema/mono-agent.config.schema.json +183 -47
  211. package/skills/mono-agent-composer/SKILL.md +2 -2
  212. package/skills/mono-agent-composer/references/config-blueprint.md +43 -40
  213. package/skills/mono-agent-composer/references/discovery-questions.md +8 -13
  214. package/skills/mono-agent-composer/references/feature-coverage.md +10 -8
  215. package/skills/mono-agent-composer/references/package-map.md +21 -15
  216. package/skills/mono-agent-composer/references/playbooks.md +19 -23
  217. package/dist/codex-model-catalog.d.ts +0 -15
  218. package/dist/codex-model-catalog.d.ts.map +0 -1
  219. package/dist/codex-model-catalog.js +0 -220
  220. package/dist/codex-model-catalog.js.map +0 -1
@@ -1,13 +1,10 @@
1
- import { chmod, mkdir, mkdtemp, open, rm } from "node:fs/promises";
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 { discoverClaudeSdkModels } from "@mono-agent/runtime-adapter";
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 { credentialNeutralProviderStatusEnvironment, hasDurableProviderEnvironmentCredential, runBoundedProviderCommand, } from "../provider-setup.js";
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 DEFAULT_OPENCODE_DISCOVERY_TIMEOUT_MS = 5000;
46
- const PI_OPENAI_CODEX_PROVIDER = "openai-codex";
47
- const OPENAI_CODEX_MODELS = [
48
- { id: "gpt-5.6-terra", name: "GPT-5.6 Terra", minimumCodexCliVersion: [0, 144, 0] },
49
- { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", minimumCodexCliVersion: [0, 144, 0] },
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
- ...OPENAI_CODEX_MODELS.map(staticDirectCodexCandidate),
53
- ...[
54
- ["claude-sonnet-5", "Claude Sonnet 5", ["low", "medium", "high", "xhigh", "max"]],
55
- ["claude-opus-4-8[1m]", "Claude Opus 4.8 (1M context)", ["low", "medium", "high", "xhigh", "max"]],
56
- ["claude-haiku-4-5-20251001", "Claude Haiku 4.5", []],
57
- ].map(([model, label, efforts]) => ({
58
- value: `claude:${model}`,
59
- label: label,
60
- hint: "SDK-versioned cached catalog; sign-in required",
61
- source: "claude",
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 [codex, pi, claude, opencode, ollama, lmstudio] = await Promise.all([
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: [codex.status, pi.status, claude.status, opencode.status, ollama.status, lmstudio.status],
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
- if (!modelRef.startsWith("pi:")) {
117
+ const separator = modelRef.indexOf(":");
118
+ if (separator <= 0 || separator === modelRef.length - 1)
112
119
  return undefined;
113
- }
114
- const [, provider, ...modelParts] = modelRef.split(":");
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 (hasDurableProviderEnvironmentCredential(`pi:${provider}:credential-check`, opts.persistedEnv ?? {})) {
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
- && hasDurableProviderEnvironmentCredential("pi:opencode-go:credential-check", process.env)) {
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 = `pi:${model.provider}:${model.id}`;
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
- && hasDurableProviderEnvironmentCredential(value, process.env);
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 = `pi:ollama:${model}`;
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 = `pi:lmstudio:${model.id}`;
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 === "opencode" || right.source === "ollama" || right.source === "lmstudio");
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
- const directCodexRank = OPENAI_CODEX_MODELS.findIndex((model) => candidate.value === directCodexRef(model));
630
- if (directCodexRank >= 0)
631
- return directCodexRank;
632
- const piOpenAiCodexRank = OPENAI_CODEX_MODELS.findIndex((model) => candidate.value === piOpenAiCodexRef(model));
633
- if (piOpenAiCodexRank >= 0)
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]);