@ouro.bot/cli 0.1.0-alpha.413 → 0.1.0-alpha.415
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/changelog.json +18 -0
- package/dist/heart/daemon/agent-config-check.js +16 -2
- package/dist/heart/daemon/cli-exec.js +11 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +20 -0
- package/dist/heart/providers/openai-codex.js +25 -11
- package/dist/repertoire/vault-unlock.js +4 -13
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.415",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Transient vault errors (timeout, ECONNREFUSED, socket hang up) are now classified separately from vault-locked errors in `ouro up` provider checks -- operators see retry guidance instead of misleading unlock/replace/recover instructions.",
|
|
8
|
+
"Fix text across vault unlock, vault create, missing credential, and failed ping results tightened to concise single-line instructions.",
|
|
9
|
+
"`@ouro.bot/cli` and the `ouro.bot` wrapper are version-synced for the error classification release."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.1.0-alpha.414",
|
|
14
|
+
"changes": [
|
|
15
|
+
"`openai-codex` live checks now use the same Responses API request shape as real Codex turns, so `ouro up` and `ouro auth verify` stop reporting false `400 status code (no body)` failures for healthy GPT-5.4 credentials.",
|
|
16
|
+
"`ouro up` now detects daemon roster drift when enabled agent bundles change on disk and restarts the stale daemon, which removes ghost agents like a locally-removed `ouroboros` from the repair queue instead of pretending they still live here.",
|
|
17
|
+
"Bundle skeleton contract coverage now validates whichever local agent bundles actually exist, so one-agent machines can keep `slugger` installed without failing the full test suite just because `ouroboros` was intentionally removed.",
|
|
18
|
+
"Expanded Codex provider runtime coverage to exercise the real turn path, preserved output-item turn state, runtime error classification, and the ping callback bundle, which keeps the global 100% coverage gate green for this repair.",
|
|
19
|
+
"`@ouro.bot/cli` and the `ouro.bot` wrapper are version-synced for the Codex live-check and daemon-roster drift repair release."
|
|
20
|
+
]
|
|
21
|
+
},
|
|
4
22
|
{
|
|
5
23
|
"version": "0.1.0-alpha.413",
|
|
6
24
|
"changes": [
|
|
@@ -233,7 +233,7 @@ function missingCredentialResult(agentName, lane, provider, model, credentialPat
|
|
|
233
233
|
return {
|
|
234
234
|
ok: false,
|
|
235
235
|
error: `${lane} provider ${provider} model ${model} has no credentials in ${agentName}'s vault at ${credentialPath}`,
|
|
236
|
-
fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to authenticate
|
|
236
|
+
fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to authenticate.`,
|
|
237
237
|
issue: (0, readiness_repair_1.providerCredentialMissingIssue)({
|
|
238
238
|
agentName,
|
|
239
239
|
lane,
|
|
@@ -243,7 +243,21 @@ function missingCredentialResult(agentName, lane, provider, model, credentialPat
|
|
|
243
243
|
}),
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
|
+
function isTransientVaultError(error) {
|
|
247
|
+
const normalized = error.toLowerCase();
|
|
248
|
+
return (normalized.includes("timed out") ||
|
|
249
|
+
normalized.includes("econnrefused") ||
|
|
250
|
+
normalized.includes("socket hang up") ||
|
|
251
|
+
normalized.includes("etimedout"));
|
|
252
|
+
}
|
|
246
253
|
function invalidPoolResult(agentName, lane, provider, model, pool) {
|
|
254
|
+
if (pool.reason === "unavailable" && isTransientVaultError(pool.error)) {
|
|
255
|
+
return {
|
|
256
|
+
ok: false,
|
|
257
|
+
error: `${lane} provider ${provider} model ${model} cannot read provider credentials from ${agentName}'s vault: ${pool.error}`,
|
|
258
|
+
fix: `Vault read timed out -- this usually resolves on retry. Run 'ouro up' again.`,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
247
261
|
if (pool.reason === "unavailable" && isVaultLockedError(pool.error)) {
|
|
248
262
|
return {
|
|
249
263
|
ok: false,
|
|
@@ -284,7 +298,7 @@ function failedPingResult(agentName, lane, provider, model, result) {
|
|
|
284
298
|
return {
|
|
285
299
|
ok: false,
|
|
286
300
|
error: `${lane} provider ${provider} model ${model} failed live check: ${result.message}`,
|
|
287
|
-
fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to refresh credentials
|
|
301
|
+
fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to refresh credentials.`,
|
|
288
302
|
issue: (0, readiness_repair_1.providerLiveCheckFailedIssue)({
|
|
289
303
|
agentName,
|
|
290
304
|
lane,
|
|
@@ -157,6 +157,10 @@ async function listCliAgents(deps) {
|
|
|
157
157
|
}
|
|
158
158
|
return [];
|
|
159
159
|
}
|
|
160
|
+
function managedAgentsSignature(agentNames) {
|
|
161
|
+
const unique = [...new Set(agentNames.map((agent) => agent.trim()).filter((agent) => agent.length > 0))].sort();
|
|
162
|
+
return unique.length > 0 ? unique.join(",") : "(none)";
|
|
163
|
+
}
|
|
160
164
|
async function checkAlreadyRunningAgentProviders(deps, onProgress) {
|
|
161
165
|
return checkAgentProviders(deps, undefined, onProgress);
|
|
162
166
|
}
|
|
@@ -267,6 +271,9 @@ async function ensureDaemonRunning(deps, options = {}) {
|
|
|
267
271
|
const alive = options.initialAlive ?? await deps.checkSocketAlive(deps.socketPath);
|
|
268
272
|
if (alive) {
|
|
269
273
|
const localRuntime = (0, runtime_metadata_1.getRuntimeMetadata)();
|
|
274
|
+
const localManagedAgents = managedAgentsSignature((0, agent_discovery_1.listEnabledBundleAgents)({
|
|
275
|
+
bundlesRoot: deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(),
|
|
276
|
+
}));
|
|
270
277
|
let runningRuntimePromise = null;
|
|
271
278
|
const fetchRunningRuntimeMetadata = async () => {
|
|
272
279
|
runningRuntimePromise ??= (async () => {
|
|
@@ -277,6 +284,9 @@ async function ensureDaemonRunning(deps, options = {}) {
|
|
|
277
284
|
lastUpdated: payload?.overview.lastUpdated ?? "unknown",
|
|
278
285
|
repoRoot: payload?.overview.repoRoot ?? "unknown",
|
|
279
286
|
configFingerprint: payload?.overview.configFingerprint ?? "unknown",
|
|
287
|
+
managedAgents: payload && payload.workers.length > 0
|
|
288
|
+
? managedAgentsSignature(payload.workers.map((worker) => worker.agent))
|
|
289
|
+
: "unknown",
|
|
280
290
|
};
|
|
281
291
|
})();
|
|
282
292
|
return runningRuntimePromise;
|
|
@@ -287,6 +297,7 @@ async function ensureDaemonRunning(deps, options = {}) {
|
|
|
287
297
|
localLastUpdated: localRuntime.lastUpdated,
|
|
288
298
|
localRepoRoot: localRuntime.repoRoot,
|
|
289
299
|
localConfigFingerprint: localRuntime.configFingerprint,
|
|
300
|
+
localManagedAgents,
|
|
290
301
|
fetchRunningVersion: async () => (await fetchRunningRuntimeMetadata()).version,
|
|
291
302
|
fetchRunningRuntimeMetadata,
|
|
292
303
|
stopDaemon: async () => {
|
|
@@ -32,6 +32,7 @@ function normalizeRuntimeIdentity(value) {
|
|
|
32
32
|
lastUpdated: typeof value.lastUpdated === "string" ? value.lastUpdated : "unknown",
|
|
33
33
|
repoRoot: typeof value.repoRoot === "string" ? value.repoRoot : "unknown",
|
|
34
34
|
configFingerprint: typeof value.configFingerprint === "string" ? value.configFingerprint : "unknown",
|
|
35
|
+
managedAgents: typeof value.managedAgents === "string" ? value.managedAgents : "unknown",
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
38
|
async function readRunningRuntimeIdentity(deps) {
|
|
@@ -70,6 +71,16 @@ function collectRuntimeDriftReasons(local, running) {
|
|
|
70
71
|
running: running.configFingerprint,
|
|
71
72
|
});
|
|
72
73
|
}
|
|
74
|
+
if (isKnownRuntimeValue(local.managedAgents)
|
|
75
|
+
&& isKnownRuntimeValue(running.managedAgents)
|
|
76
|
+
&& local.managedAgents !== running.managedAgents) {
|
|
77
|
+
reasons.push({
|
|
78
|
+
key: "managedAgents",
|
|
79
|
+
label: "managed agents",
|
|
80
|
+
local: local.managedAgents,
|
|
81
|
+
running: running.managedAgents,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
73
84
|
return reasons;
|
|
74
85
|
}
|
|
75
86
|
function formatRuntimeValue(reason) {
|
|
@@ -87,6 +98,7 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
87
98
|
lastUpdated: deps.localLastUpdated,
|
|
88
99
|
repoRoot: deps.localRepoRoot,
|
|
89
100
|
configFingerprint: deps.localConfigFingerprint,
|
|
101
|
+
managedAgents: deps.localManagedAgents,
|
|
90
102
|
});
|
|
91
103
|
try {
|
|
92
104
|
const runningRuntime = await readRunningRuntimeIdentity(deps);
|
|
@@ -118,10 +130,12 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
118
130
|
localLastUpdated: localRuntime.lastUpdated,
|
|
119
131
|
localRepoRoot: localRuntime.repoRoot,
|
|
120
132
|
localConfigFingerprint: localRuntime.configFingerprint,
|
|
133
|
+
localManagedAgents: localRuntime.managedAgents,
|
|
121
134
|
runningVersion,
|
|
122
135
|
runningLastUpdated: runningRuntime.lastUpdated,
|
|
123
136
|
runningRepoRoot: runningRuntime.repoRoot,
|
|
124
137
|
runningConfigFingerprint: runningRuntime.configFingerprint,
|
|
138
|
+
runningManagedAgents: runningRuntime.managedAgents,
|
|
125
139
|
action: "stale_replace_failed",
|
|
126
140
|
driftKeys: driftReasons.map((entry) => entry.key),
|
|
127
141
|
reason,
|
|
@@ -153,10 +167,12 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
153
167
|
localLastUpdated: localRuntime.lastUpdated,
|
|
154
168
|
localRepoRoot: localRuntime.repoRoot,
|
|
155
169
|
localConfigFingerprint: localRuntime.configFingerprint,
|
|
170
|
+
localManagedAgents: localRuntime.managedAgents,
|
|
156
171
|
runningVersion,
|
|
157
172
|
runningLastUpdated: runningRuntime.lastUpdated,
|
|
158
173
|
runningRepoRoot: runningRuntime.repoRoot,
|
|
159
174
|
runningConfigFingerprint: runningRuntime.configFingerprint,
|
|
175
|
+
runningManagedAgents: runningRuntime.managedAgents,
|
|
160
176
|
action: "stale_restarted",
|
|
161
177
|
driftKeys: driftReasons.map((entry) => entry.key),
|
|
162
178
|
pid: started.pid ?? null,
|
|
@@ -179,10 +195,12 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
179
195
|
localLastUpdated: localRuntime.lastUpdated,
|
|
180
196
|
localRepoRoot: localRuntime.repoRoot,
|
|
181
197
|
localConfigFingerprint: localRuntime.configFingerprint,
|
|
198
|
+
localManagedAgents: localRuntime.managedAgents,
|
|
182
199
|
runningVersion,
|
|
183
200
|
runningLastUpdated: runningRuntime.lastUpdated,
|
|
184
201
|
runningRepoRoot: runningRuntime.repoRoot,
|
|
185
202
|
runningConfigFingerprint: runningRuntime.configFingerprint,
|
|
203
|
+
runningManagedAgents: runningRuntime.managedAgents,
|
|
186
204
|
action: "unknown_version",
|
|
187
205
|
},
|
|
188
206
|
});
|
|
@@ -206,6 +224,7 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
206
224
|
localLastUpdated: localRuntime.lastUpdated,
|
|
207
225
|
localRepoRoot: localRuntime.repoRoot,
|
|
208
226
|
localConfigFingerprint: localRuntime.configFingerprint,
|
|
227
|
+
localManagedAgents: localRuntime.managedAgents,
|
|
209
228
|
action: "status_lookup_failed",
|
|
210
229
|
reason,
|
|
211
230
|
},
|
|
@@ -228,6 +247,7 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
228
247
|
localLastUpdated: localRuntime.lastUpdated,
|
|
229
248
|
localRepoRoot: localRuntime.repoRoot,
|
|
230
249
|
localConfigFingerprint: localRuntime.configFingerprint,
|
|
250
|
+
localManagedAgents: localRuntime.managedAgents,
|
|
231
251
|
action: "already_current",
|
|
232
252
|
},
|
|
233
253
|
});
|
|
@@ -20,6 +20,16 @@ const OPENAI_CODEX_AUTH_FAILURE_MARKERS = [
|
|
|
20
20
|
"invalid bearer token",
|
|
21
21
|
];
|
|
22
22
|
const OPENAI_CODEX_BACKEND_BASE_URL = "https://chatgpt.com/backend-api/codex";
|
|
23
|
+
const OPENAI_CODEX_PING_INPUT = [{ role: "user", content: "ping" }];
|
|
24
|
+
const OPENAI_CODEX_PING_CALLBACKS = {
|
|
25
|
+
onModelStart() { },
|
|
26
|
+
onModelStreamStart() { },
|
|
27
|
+
onTextChunk() { },
|
|
28
|
+
onReasoningChunk() { },
|
|
29
|
+
onToolStart() { },
|
|
30
|
+
onToolEnd() { },
|
|
31
|
+
onError() { },
|
|
32
|
+
};
|
|
23
33
|
function getOpenAICodexAgentNameForGuidance() {
|
|
24
34
|
return (0, identity_1.getAgentName)();
|
|
25
35
|
}
|
|
@@ -82,6 +92,18 @@ function getChatGPTAccountIdFromToken(token) {
|
|
|
82
92
|
return "";
|
|
83
93
|
return accountId.trim();
|
|
84
94
|
}
|
|
95
|
+
function createOpenAICodexResponsesParams(input, instructions, model, reasoningEffort) {
|
|
96
|
+
return {
|
|
97
|
+
model,
|
|
98
|
+
input,
|
|
99
|
+
instructions,
|
|
100
|
+
tools: [],
|
|
101
|
+
reasoning: { effort: reasoningEffort, summary: "detailed" },
|
|
102
|
+
stream: true,
|
|
103
|
+
store: false,
|
|
104
|
+
include: ["reasoning.encrypted_content"],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
85
107
|
function createOpenAICodexProviderRuntime(model, codexConfig = (0, config_1.getOpenAICodexConfig)()) {
|
|
86
108
|
(0, runtime_1.emitNervesEvent)({
|
|
87
109
|
component: "engine",
|
|
@@ -137,16 +159,8 @@ function createOpenAICodexProviderRuntime(model, codexConfig = (0, config_1.getO
|
|
|
137
159
|
async streamTurn(request) {
|
|
138
160
|
if (!nativeInput)
|
|
139
161
|
this.resetTurnState(request.messages);
|
|
140
|
-
const params =
|
|
141
|
-
|
|
142
|
-
input: nativeInput,
|
|
143
|
-
instructions: nativeInstructions,
|
|
144
|
-
tools: (0, streaming_1.toResponsesTools)(request.activeTools),
|
|
145
|
-
reasoning: { effort: request.reasoningEffort ?? "medium", summary: "detailed" },
|
|
146
|
-
stream: true,
|
|
147
|
-
store: false,
|
|
148
|
-
include: ["reasoning.encrypted_content"],
|
|
149
|
-
};
|
|
162
|
+
const params = createOpenAICodexResponsesParams(nativeInput, nativeInstructions, this.model, request.reasoningEffort ?? "medium");
|
|
163
|
+
params.tools = (0, streaming_1.toResponsesTools)(request.activeTools);
|
|
150
164
|
if (request.toolChoiceRequired)
|
|
151
165
|
params.tool_choice = "required";
|
|
152
166
|
try {
|
|
@@ -161,7 +175,7 @@ function createOpenAICodexProviderRuntime(model, codexConfig = (0, config_1.getO
|
|
|
161
175
|
},
|
|
162
176
|
/* v8 ignore start -- ping: tested via provider-ping.test.ts @preserve */
|
|
163
177
|
async ping(signal) {
|
|
164
|
-
await this.client
|
|
178
|
+
await (0, streaming_1.streamResponsesApi)(this.client, createOpenAICodexResponsesParams(OPENAI_CODEX_PING_INPUT, "", this.model, "medium"), OPENAI_CODEX_PING_CALLBACKS, signal);
|
|
165
179
|
},
|
|
166
180
|
/* v8 ignore stop */
|
|
167
181
|
/* v8 ignore next 3 -- delegation: classification logic tested via classifyOpenAICodexError @preserve */
|
|
@@ -101,13 +101,8 @@ function missingSecureStoreMessage(config) {
|
|
|
101
101
|
: "Run `ouro vault unlock --store plaintext-file` to store the vault unlock secret in a chmod 0600 local file.",
|
|
102
102
|
].join("\n");
|
|
103
103
|
}
|
|
104
|
-
function vaultUnlockReplaceRecoverFix(agentName,
|
|
105
|
-
return
|
|
106
|
-
`Run 'ouro vault unlock --agent ${agentName}' if you have the saved vault unlock secret.`,
|
|
107
|
-
`If this agent predates vault auth or nobody saved the unlock secret, run 'ouro vault replace --agent ${agentName}' to create a new empty vault, then re-auth/re-enter credentials.`,
|
|
108
|
-
`If you do have a local JSON credential export, run 'ouro vault recover --agent ${agentName} --from <json>' to create the agent vault and import it.`,
|
|
109
|
-
nextStep,
|
|
110
|
-
].join(" ");
|
|
104
|
+
function vaultUnlockReplaceRecoverFix(agentName, _nextStep) {
|
|
105
|
+
return `Run 'ouro vault unlock --agent ${agentName}' or 'ouro vault replace --agent ${agentName}' if the secret is lost.`;
|
|
111
106
|
}
|
|
112
107
|
function credentialVaultNotConfiguredError(agentName, configPath) {
|
|
113
108
|
return (`${CREDENTIAL_VAULT_NOT_CONFIGURED_PREFIX}${configPath}. ` +
|
|
@@ -116,12 +111,8 @@ function credentialVaultNotConfiguredError(agentName, configPath) {
|
|
|
116
111
|
function isCredentialVaultNotConfiguredError(message) {
|
|
117
112
|
return message.includes(CREDENTIAL_VAULT_NOT_CONFIGURED_PREFIX);
|
|
118
113
|
}
|
|
119
|
-
function vaultCreateRecoverFix(agentName,
|
|
120
|
-
return
|
|
121
|
-
`Run 'ouro vault create --agent ${agentName}' to create this agent's vault.`,
|
|
122
|
-
`If you still have a local JSON credential export from an earlier alpha, run 'ouro vault recover --agent ${agentName} --from <json>' instead.`,
|
|
123
|
-
nextStep,
|
|
124
|
-
].join(" ");
|
|
114
|
+
function vaultCreateRecoverFix(agentName, _nextStep) {
|
|
115
|
+
return `Run 'ouro vault create --agent ${agentName}' to set up this agent's vault.`;
|
|
125
116
|
}
|
|
126
117
|
function vaultUnlockSecretStrengthIssues(secret) {
|
|
127
118
|
const issues = [];
|