@ouro.bot/cli 0.1.0-alpha.13 → 0.1.0-alpha.131
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/AdoptionSpecialist.ouro/psyche/SOUL.md +2 -2
- package/AdoptionSpecialist.ouro/psyche/identities/monty.md +2 -2
- package/README.md +147 -205
- package/changelog.json +814 -0
- package/dist/heart/active-work.js +622 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/commitments.js +105 -0
- package/dist/heart/config.js +66 -21
- package/dist/heart/core.js +518 -100
- package/dist/heart/cross-chat-delivery.js +146 -0
- package/dist/heart/daemon/agent-discovery.js +81 -0
- package/dist/heart/daemon/auth-flow.js +457 -0
- package/dist/heart/daemon/daemon-cli.js +1516 -195
- package/dist/heart/daemon/daemon-entry.js +43 -2
- package/dist/heart/daemon/daemon-runtime-sync.js +212 -0
- package/dist/heart/daemon/daemon.js +261 -1
- package/dist/heart/daemon/hatch-animation.js +10 -3
- package/dist/heart/daemon/hatch-flow.js +7 -72
- package/dist/heart/daemon/hooks/bundle-meta.js +92 -0
- package/dist/heart/daemon/launchd.js +159 -0
- package/dist/heart/daemon/log-tailer.js +4 -3
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/ouro-bot-global-installer.js +128 -0
- package/dist/heart/daemon/ouro-path-installer.js +57 -29
- package/dist/heart/daemon/ouro-version-manager.js +171 -0
- package/dist/heart/daemon/process-manager.js +13 -0
- package/dist/heart/daemon/run-hooks.js +37 -0
- package/dist/heart/daemon/runtime-logging.js +58 -15
- package/dist/heart/daemon/runtime-metadata.js +219 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/sense-manager.js +50 -2
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- package/dist/heart/daemon/socket-client.js +202 -0
- package/dist/heart/daemon/specialist-orchestrator.js +2 -2
- package/dist/heart/daemon/specialist-prompt.js +7 -4
- package/dist/heart/daemon/specialist-tools.js +52 -3
- package/dist/heart/daemon/staged-restart.js +114 -0
- package/dist/heart/daemon/thoughts.js +507 -0
- package/dist/heart/daemon/update-checker.js +111 -0
- package/dist/heart/daemon/update-hooks.js +138 -0
- package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/identity.js +64 -21
- package/dist/heart/kicks.js +1 -19
- package/dist/heart/model-capabilities.js +48 -0
- package/dist/heart/obligations.js +197 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +159 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +195 -34
- package/dist/heart/providers/azure.js +115 -9
- package/dist/heart/providers/github-copilot.js +157 -0
- package/dist/heart/providers/minimax.js +33 -3
- package/dist/heart/providers/openai-codex.js +49 -14
- package/dist/heart/safe-workspace.js +381 -0
- package/dist/heart/session-activity.js +173 -0
- package/dist/heart/session-recall.js +216 -0
- package/dist/heart/streaming.js +108 -24
- package/dist/heart/target-resolution.js +123 -0
- package/dist/heart/tool-loop.js +194 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/mind/associative-recall.js +14 -2
- package/dist/mind/bundle-manifest.js +12 -0
- package/dist/mind/context.js +60 -14
- package/dist/mind/first-impressions.js +16 -2
- package/dist/mind/friends/channel.js +35 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/store-file.js +19 -0
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +8 -0
- package/dist/mind/memory.js +27 -26
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +456 -77
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +15 -2
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/index.js +12 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/repertoire/ado-client.js +4 -2
- package/dist/repertoire/coding/context-pack.js +254 -0
- package/dist/repertoire/coding/feedback.js +301 -0
- package/dist/repertoire/coding/index.js +4 -1
- package/dist/repertoire/coding/manager.js +210 -4
- package/dist/repertoire/coding/spawner.js +39 -9
- package/dist/repertoire/coding/tools.js +171 -4
- package/dist/repertoire/data/ado-endpoints.json +188 -0
- package/dist/repertoire/guardrails.js +290 -0
- package/dist/repertoire/mcp-client.js +254 -0
- package/dist/repertoire/mcp-manager.js +198 -0
- package/dist/repertoire/skills.js +3 -26
- package/dist/repertoire/tasks/board.js +12 -0
- package/dist/repertoire/tasks/index.js +23 -9
- package/dist/repertoire/tasks/transitions.js +1 -2
- package/dist/repertoire/tools-base.js +925 -250
- package/dist/repertoire/tools-bluebubbles.js +93 -0
- package/dist/repertoire/tools-teams.js +58 -25
- package/dist/repertoire/tools.js +106 -53
- package/dist/senses/bluebubbles-client.js +210 -5
- package/dist/senses/bluebubbles-entry.js +2 -0
- package/dist/senses/bluebubbles-inbound-log.js +109 -0
- package/dist/senses/bluebubbles-media.js +339 -0
- package/dist/senses/bluebubbles-model.js +12 -4
- package/dist/senses/bluebubbles-mutation-log.js +45 -5
- package/dist/senses/bluebubbles-runtime-state.js +109 -0
- package/dist/senses/bluebubbles-session-cleanup.js +72 -0
- package/dist/senses/bluebubbles.js +915 -45
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +374 -131
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/debug-activity.js +154 -0
- package/dist/senses/inner-dialog-worker.js +47 -18
- package/dist/senses/inner-dialog.js +388 -83
- package/dist/senses/pipeline.js +444 -0
- package/dist/senses/teams.js +607 -129
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +9 -3
- package/subagents/README.md +4 -70
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.classifyGithubCopilotError = classifyGithubCopilotError;
|
|
7
|
+
exports.createGithubCopilotProviderRuntime = createGithubCopilotProviderRuntime;
|
|
8
|
+
const openai_1 = __importDefault(require("openai"));
|
|
9
|
+
const config_1 = require("../config");
|
|
10
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
11
|
+
const streaming_1 = require("../streaming");
|
|
12
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
13
|
+
/* v8 ignore start -- duplicated from shared provider utils, tested there @preserve */
|
|
14
|
+
function isNetworkError(error) {
|
|
15
|
+
const code = error.code || "";
|
|
16
|
+
if (["ECONNRESET", "ECONNREFUSED", "ENOTFOUND", "ETIMEDOUT", "EPIPE",
|
|
17
|
+
"EAI_AGAIN", "EHOSTUNREACH", "ENETUNREACH", "ECONNABORTED"].includes(code))
|
|
18
|
+
return true;
|
|
19
|
+
const msg = error.message || "";
|
|
20
|
+
return msg.includes("fetch failed") || msg.includes("socket hang up") || msg.includes("getaddrinfo");
|
|
21
|
+
}
|
|
22
|
+
/* v8 ignore stop */
|
|
23
|
+
/* v8 ignore start -- duplicated classification pattern, tested via provider unit tests @preserve */
|
|
24
|
+
function classifyGithubCopilotError(error) {
|
|
25
|
+
const status = error.status;
|
|
26
|
+
if (status === 401 || status === 403)
|
|
27
|
+
return "auth-failure";
|
|
28
|
+
if (status === 429)
|
|
29
|
+
return "rate-limit";
|
|
30
|
+
if (status && status >= 500)
|
|
31
|
+
return "server-error";
|
|
32
|
+
if (isNetworkError(error))
|
|
33
|
+
return "network-error";
|
|
34
|
+
return "unknown";
|
|
35
|
+
}
|
|
36
|
+
/* v8 ignore stop */
|
|
37
|
+
function createGithubCopilotProviderRuntime(injectedConfig) {
|
|
38
|
+
(0, runtime_1.emitNervesEvent)({
|
|
39
|
+
component: "engine",
|
|
40
|
+
event: "engine.provider_init",
|
|
41
|
+
message: "github-copilot provider init",
|
|
42
|
+
meta: { provider: "github-copilot" },
|
|
43
|
+
});
|
|
44
|
+
const config = injectedConfig ?? (0, config_1.getGithubCopilotConfig)();
|
|
45
|
+
if (!config.githubToken) {
|
|
46
|
+
throw new Error("provider 'github-copilot' is selected in agent.json but providers.github-copilot.githubToken is missing in secrets.json.");
|
|
47
|
+
}
|
|
48
|
+
if (!config.baseUrl) {
|
|
49
|
+
throw new Error("provider 'github-copilot' is selected in agent.json but providers.github-copilot.baseUrl is missing in secrets.json.");
|
|
50
|
+
}
|
|
51
|
+
const isCompletionsModel = config.model.startsWith("claude");
|
|
52
|
+
const modelCaps = (0, model_capabilities_1.getModelCapabilities)(config.model);
|
|
53
|
+
const capabilities = new Set();
|
|
54
|
+
/* v8 ignore next -- branch: capability detection tested via unit test @preserve */
|
|
55
|
+
if (modelCaps.reasoningEffort)
|
|
56
|
+
capabilities.add("reasoning-effort");
|
|
57
|
+
const client = new openai_1.default({
|
|
58
|
+
apiKey: config.githubToken,
|
|
59
|
+
baseURL: config.baseUrl,
|
|
60
|
+
timeout: 30000,
|
|
61
|
+
maxRetries: 0,
|
|
62
|
+
});
|
|
63
|
+
if (isCompletionsModel) {
|
|
64
|
+
// Chat completions path (Claude models via Copilot)
|
|
65
|
+
return {
|
|
66
|
+
id: "github-copilot",
|
|
67
|
+
model: config.model,
|
|
68
|
+
client,
|
|
69
|
+
capabilities,
|
|
70
|
+
supportedReasoningEfforts: modelCaps.reasoningEffort,
|
|
71
|
+
resetTurnState(_messages) {
|
|
72
|
+
// No provider-owned turn state for chat-completions path.
|
|
73
|
+
},
|
|
74
|
+
appendToolOutput(_callId, _output) {
|
|
75
|
+
// Chat-completions providers rely on canonical messages only.
|
|
76
|
+
},
|
|
77
|
+
/* v8 ignore start -- streamTurn: tested via mock assertions in github-copilot.test.ts @preserve */
|
|
78
|
+
async streamTurn(request) {
|
|
79
|
+
const params = {
|
|
80
|
+
messages: request.messages,
|
|
81
|
+
tools: request.activeTools,
|
|
82
|
+
stream: true,
|
|
83
|
+
};
|
|
84
|
+
if (this.model)
|
|
85
|
+
params.model = this.model;
|
|
86
|
+
if (request.traceId)
|
|
87
|
+
params.metadata = { trace_id: request.traceId };
|
|
88
|
+
if (request.toolChoiceRequired)
|
|
89
|
+
params.tool_choice = "required";
|
|
90
|
+
try {
|
|
91
|
+
return await (0, streaming_1.streamChatCompletion)(this.client, params, request.callbacks, request.signal, request.eagerFinalAnswerStreaming);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
/* v8 ignore stop */
|
|
98
|
+
/* v8 ignore next 3 -- delegation: classification logic tested via classifyGithubCopilotError @preserve */
|
|
99
|
+
classifyError(error) {
|
|
100
|
+
return classifyGithubCopilotError(error);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Responses API path (GPT models via Copilot)
|
|
105
|
+
let nativeInput = null;
|
|
106
|
+
let nativeInstructions = "";
|
|
107
|
+
return {
|
|
108
|
+
id: "github-copilot",
|
|
109
|
+
model: config.model,
|
|
110
|
+
client,
|
|
111
|
+
capabilities,
|
|
112
|
+
supportedReasoningEfforts: modelCaps.reasoningEffort,
|
|
113
|
+
/* v8 ignore start -- responses path: tested via mock assertions in github-copilot.test.ts @preserve */
|
|
114
|
+
resetTurnState(messages) {
|
|
115
|
+
const { instructions, input } = (0, streaming_1.toResponsesInput)(messages);
|
|
116
|
+
nativeInput = input;
|
|
117
|
+
nativeInstructions = instructions;
|
|
118
|
+
},
|
|
119
|
+
appendToolOutput(callId, output) {
|
|
120
|
+
if (!nativeInput)
|
|
121
|
+
return;
|
|
122
|
+
nativeInput.push({ type: "function_call_output", call_id: callId, output });
|
|
123
|
+
},
|
|
124
|
+
async streamTurn(request) {
|
|
125
|
+
if (!nativeInput)
|
|
126
|
+
this.resetTurnState(request.messages);
|
|
127
|
+
const params = {
|
|
128
|
+
model: this.model,
|
|
129
|
+
input: nativeInput,
|
|
130
|
+
instructions: nativeInstructions,
|
|
131
|
+
tools: (0, streaming_1.toResponsesTools)(request.activeTools),
|
|
132
|
+
reasoning: { effort: request.reasoningEffort ?? "medium", summary: "detailed" },
|
|
133
|
+
stream: true,
|
|
134
|
+
store: false,
|
|
135
|
+
include: ["reasoning.encrypted_content"],
|
|
136
|
+
};
|
|
137
|
+
if (request.traceId)
|
|
138
|
+
params.metadata = { trace_id: request.traceId };
|
|
139
|
+
if (request.toolChoiceRequired)
|
|
140
|
+
params.tool_choice = "required";
|
|
141
|
+
try {
|
|
142
|
+
const result = await (0, streaming_1.streamResponsesApi)(this.client, params, request.callbacks, request.signal, request.eagerFinalAnswerStreaming);
|
|
143
|
+
for (const item of result.outputItems)
|
|
144
|
+
nativeInput.push(item);
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
/* v8 ignore stop */
|
|
152
|
+
/* v8 ignore next 3 -- delegation: classification logic tested via classifyGithubCopilotError @preserve */
|
|
153
|
+
classifyError(error) {
|
|
154
|
+
return classifyGithubCopilotError(error);
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
@@ -3,22 +3,48 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.classifyMinimaxError = classifyMinimaxError;
|
|
6
7
|
exports.createMinimaxProviderRuntime = createMinimaxProviderRuntime;
|
|
7
8
|
const openai_1 = __importDefault(require("openai"));
|
|
8
9
|
const config_1 = require("../config");
|
|
9
10
|
const runtime_1 = require("../../nerves/runtime");
|
|
11
|
+
/* v8 ignore start -- shared network error utility, tested via classification tests @preserve */
|
|
12
|
+
function isNetworkError(error) {
|
|
13
|
+
const code = error.code || "";
|
|
14
|
+
if (["ECONNRESET", "ECONNREFUSED", "ENOTFOUND", "ETIMEDOUT", "EPIPE",
|
|
15
|
+
"EAI_AGAIN", "EHOSTUNREACH", "ENETUNREACH", "ECONNABORTED"].includes(code))
|
|
16
|
+
return true;
|
|
17
|
+
const msg = error.message || "";
|
|
18
|
+
return msg.includes("fetch failed") || msg.includes("socket hang up") || msg.includes("getaddrinfo");
|
|
19
|
+
}
|
|
20
|
+
/* v8 ignore stop */
|
|
21
|
+
function classifyMinimaxError(error) {
|
|
22
|
+
const status = error.status;
|
|
23
|
+
if (status === 401 || status === 403)
|
|
24
|
+
return "auth-failure";
|
|
25
|
+
if (status === 429)
|
|
26
|
+
return "rate-limit";
|
|
27
|
+
if (status && status >= 500)
|
|
28
|
+
return "server-error";
|
|
29
|
+
if (isNetworkError(error))
|
|
30
|
+
return "network-error";
|
|
31
|
+
return "unknown";
|
|
32
|
+
}
|
|
10
33
|
const streaming_1 = require("../streaming");
|
|
11
|
-
|
|
34
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
35
|
+
function createMinimaxProviderRuntime(config) {
|
|
12
36
|
(0, runtime_1.emitNervesEvent)({
|
|
13
37
|
component: "engine",
|
|
14
38
|
event: "engine.provider_init",
|
|
15
39
|
message: "minimax provider init",
|
|
16
40
|
meta: { provider: "minimax" },
|
|
17
41
|
});
|
|
18
|
-
const minimaxConfig = (0, config_1.getMinimaxConfig)();
|
|
42
|
+
const minimaxConfig = config ?? (0, config_1.getMinimaxConfig)();
|
|
19
43
|
if (!minimaxConfig.apiKey) {
|
|
20
44
|
throw new Error("provider 'minimax' is selected in agent.json but providers.minimax.apiKey is missing in secrets.json.");
|
|
21
45
|
}
|
|
46
|
+
// Registry consulted; MiniMax models return empty defaults (no capabilities to derive)
|
|
47
|
+
(0, model_capabilities_1.getModelCapabilities)(minimaxConfig.model);
|
|
22
48
|
const client = new openai_1.default({
|
|
23
49
|
apiKey: minimaxConfig.apiKey,
|
|
24
50
|
baseURL: "https://api.minimaxi.chat/v1",
|
|
@@ -29,6 +55,7 @@ function createMinimaxProviderRuntime() {
|
|
|
29
55
|
id: "minimax",
|
|
30
56
|
model: minimaxConfig.model,
|
|
31
57
|
client,
|
|
58
|
+
capabilities: new Set(),
|
|
32
59
|
resetTurnState(_messages) {
|
|
33
60
|
// No provider-owned turn state for chat-completions providers.
|
|
34
61
|
},
|
|
@@ -47,7 +74,10 @@ function createMinimaxProviderRuntime() {
|
|
|
47
74
|
params.metadata = { trace_id: request.traceId };
|
|
48
75
|
if (request.toolChoiceRequired)
|
|
49
76
|
params.tool_choice = "required";
|
|
50
|
-
return (0, streaming_1.streamChatCompletion)(this.client, params, request.callbacks, request.signal);
|
|
77
|
+
return (0, streaming_1.streamChatCompletion)(this.client, params, request.callbacks, request.signal, request.eagerFinalAnswerStreaming);
|
|
78
|
+
},
|
|
79
|
+
classifyError(error) {
|
|
80
|
+
return classifyMinimaxError(error);
|
|
51
81
|
},
|
|
52
82
|
};
|
|
53
83
|
}
|
|
@@ -3,12 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.classifyOpenAICodexError = classifyOpenAICodexError;
|
|
6
7
|
exports.createOpenAICodexProviderRuntime = createOpenAICodexProviderRuntime;
|
|
7
8
|
const openai_1 = __importDefault(require("openai"));
|
|
8
9
|
const config_1 = require("../config");
|
|
9
10
|
const identity_1 = require("../identity");
|
|
10
11
|
const runtime_1 = require("../../nerves/runtime");
|
|
11
12
|
const streaming_1 = require("../streaming");
|
|
13
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
12
14
|
const OPENAI_CODEX_AUTH_FAILURE_MARKERS = [
|
|
13
15
|
"authentication failed",
|
|
14
16
|
"unauthorized",
|
|
@@ -27,11 +29,11 @@ function getOpenAICodexOAuthInstructions() {
|
|
|
27
29
|
const agentName = getOpenAICodexAgentNameForGuidance();
|
|
28
30
|
return [
|
|
29
31
|
"Fix:",
|
|
30
|
-
` 1. Run \`
|
|
31
|
-
" (or run `codex login` and set the OAuth token manually)",
|
|
32
|
+
` 1. Run \`ouro auth --agent ${agentName}\``,
|
|
32
33
|
` 2. Open ${getOpenAICodexSecretsPathForGuidance()}`,
|
|
33
34
|
" 3. Confirm providers.openai-codex.oauthAccessToken is set",
|
|
34
35
|
" 4. This provider uses chatgpt.com/backend-api/codex/responses (not api.openai.com/responses).",
|
|
36
|
+
" 5. After reauth, retry the failed ouro command or reconnect this session.",
|
|
35
37
|
].join("\n");
|
|
36
38
|
}
|
|
37
39
|
function getOpenAICodexReauthGuidance(reason) {
|
|
@@ -41,6 +43,33 @@ function getOpenAICodexReauthGuidance(reason) {
|
|
|
41
43
|
getOpenAICodexOAuthInstructions(),
|
|
42
44
|
].join("\n");
|
|
43
45
|
}
|
|
46
|
+
/* v8 ignore start -- shared network error utility, tested via classification tests @preserve */
|
|
47
|
+
function isNetworkError(error) {
|
|
48
|
+
const code = error.code || "";
|
|
49
|
+
if (["ECONNRESET", "ECONNREFUSED", "ENOTFOUND", "ETIMEDOUT", "EPIPE",
|
|
50
|
+
"EAI_AGAIN", "EHOSTUNREACH", "ENETUNREACH", "ECONNABORTED"].includes(code))
|
|
51
|
+
return true;
|
|
52
|
+
const msg = error.message || "";
|
|
53
|
+
return msg.includes("fetch failed") || msg.includes("socket hang up") || msg.includes("getaddrinfo");
|
|
54
|
+
}
|
|
55
|
+
/* v8 ignore stop */
|
|
56
|
+
function classifyOpenAICodexError(error) {
|
|
57
|
+
const status = error.status;
|
|
58
|
+
if (status === 401 || status === 403 || isOpenAICodexAuthFailure(error))
|
|
59
|
+
return "auth-failure";
|
|
60
|
+
if (status === 429) {
|
|
61
|
+
const lower = error.message.toLowerCase();
|
|
62
|
+
if (lower.includes("usage") || lower.includes("quota") || lower.includes("exceeded your"))
|
|
63
|
+
return "usage-limit";
|
|
64
|
+
return "rate-limit";
|
|
65
|
+
}
|
|
66
|
+
if (status && status >= 500)
|
|
67
|
+
return "server-error";
|
|
68
|
+
if (isNetworkError(error))
|
|
69
|
+
return "network-error";
|
|
70
|
+
return "unknown";
|
|
71
|
+
}
|
|
72
|
+
/* v8 ignore start -- auth detection: only called from classifyOpenAICodexError which always passes Error @preserve */
|
|
44
73
|
function isOpenAICodexAuthFailure(error) {
|
|
45
74
|
if (!(error instanceof Error))
|
|
46
75
|
return false;
|
|
@@ -50,13 +79,7 @@ function isOpenAICodexAuthFailure(error) {
|
|
|
50
79
|
const lower = error.message.toLowerCase();
|
|
51
80
|
return OPENAI_CODEX_AUTH_FAILURE_MARKERS.some((marker) => lower.includes(marker));
|
|
52
81
|
}
|
|
53
|
-
|
|
54
|
-
const base = error instanceof Error ? error.message : String(error);
|
|
55
|
-
if (isOpenAICodexAuthFailure(error)) {
|
|
56
|
-
return new Error(getOpenAICodexReauthGuidance(`OpenAI Codex authentication failed (${base}).`));
|
|
57
|
-
}
|
|
58
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
59
|
-
}
|
|
82
|
+
/* v8 ignore stop */
|
|
60
83
|
function decodeJwtPayload(token) {
|
|
61
84
|
const parts = token.split(".");
|
|
62
85
|
if (parts.length < 2)
|
|
@@ -87,14 +110,14 @@ function getChatGPTAccountIdFromToken(token) {
|
|
|
87
110
|
return "";
|
|
88
111
|
return accountId.trim();
|
|
89
112
|
}
|
|
90
|
-
function createOpenAICodexProviderRuntime() {
|
|
113
|
+
function createOpenAICodexProviderRuntime(config) {
|
|
91
114
|
(0, runtime_1.emitNervesEvent)({
|
|
92
115
|
component: "engine",
|
|
93
116
|
event: "engine.provider_init",
|
|
94
117
|
message: "openai-codex provider init",
|
|
95
118
|
meta: { provider: "openai-codex" },
|
|
96
119
|
});
|
|
97
|
-
const codexConfig = (0, config_1.getOpenAICodexConfig)();
|
|
120
|
+
const codexConfig = config ?? (0, config_1.getOpenAICodexConfig)();
|
|
98
121
|
if (!(codexConfig.model && codexConfig.oauthAccessToken)) {
|
|
99
122
|
throw new Error(getOpenAICodexReauthGuidance("provider 'openai-codex' is selected in agent.json but providers.openai-codex.model/oauthAccessToken is incomplete in secrets.json."));
|
|
100
123
|
}
|
|
@@ -106,6 +129,12 @@ function createOpenAICodexProviderRuntime() {
|
|
|
106
129
|
if (!chatgptAccountId) {
|
|
107
130
|
throw new Error(getOpenAICodexReauthGuidance("OpenAI Codex OAuth access token is missing a chatgpt_account_id claim required for chatgpt.com/backend-api/codex."));
|
|
108
131
|
}
|
|
132
|
+
const modelCaps = (0, model_capabilities_1.getModelCapabilities)(codexConfig.model);
|
|
133
|
+
const capabilities = new Set();
|
|
134
|
+
if (modelCaps.reasoningEffort)
|
|
135
|
+
capabilities.add("reasoning-effort");
|
|
136
|
+
if (modelCaps.phase)
|
|
137
|
+
capabilities.add("phase-annotation");
|
|
109
138
|
const client = new openai_1.default({
|
|
110
139
|
apiKey: token,
|
|
111
140
|
baseURL: OPENAI_CODEX_BACKEND_BASE_URL,
|
|
@@ -123,6 +152,8 @@ function createOpenAICodexProviderRuntime() {
|
|
|
123
152
|
id: "openai-codex",
|
|
124
153
|
model: codexConfig.model,
|
|
125
154
|
client,
|
|
155
|
+
capabilities,
|
|
156
|
+
supportedReasoningEfforts: modelCaps.reasoningEffort,
|
|
126
157
|
resetTurnState(messages) {
|
|
127
158
|
const { instructions, input } = (0, streaming_1.toResponsesInput)(messages);
|
|
128
159
|
nativeInput = input;
|
|
@@ -141,7 +172,7 @@ function createOpenAICodexProviderRuntime() {
|
|
|
141
172
|
input: nativeInput,
|
|
142
173
|
instructions: nativeInstructions,
|
|
143
174
|
tools: (0, streaming_1.toResponsesTools)(request.activeTools),
|
|
144
|
-
reasoning: { effort: "medium", summary: "detailed" },
|
|
175
|
+
reasoning: { effort: request.reasoningEffort ?? "medium", summary: "detailed" },
|
|
145
176
|
stream: true,
|
|
146
177
|
store: false,
|
|
147
178
|
include: ["reasoning.encrypted_content"],
|
|
@@ -149,14 +180,18 @@ function createOpenAICodexProviderRuntime() {
|
|
|
149
180
|
if (request.toolChoiceRequired)
|
|
150
181
|
params.tool_choice = "required";
|
|
151
182
|
try {
|
|
152
|
-
const result = await (0, streaming_1.streamResponsesApi)(this.client, params, request.callbacks, request.signal);
|
|
183
|
+
const result = await (0, streaming_1.streamResponsesApi)(this.client, params, request.callbacks, request.signal, request.eagerFinalAnswerStreaming);
|
|
153
184
|
for (const item of result.outputItems)
|
|
154
185
|
nativeInput.push(item);
|
|
155
186
|
return result;
|
|
156
187
|
}
|
|
157
188
|
catch (error) {
|
|
158
|
-
throw
|
|
189
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
159
190
|
}
|
|
160
191
|
},
|
|
192
|
+
/* v8 ignore next 3 -- delegation: classification logic tested via classifyOpenAICodexError @preserve */
|
|
193
|
+
classifyError(error) {
|
|
194
|
+
return classifyOpenAICodexError(error);
|
|
195
|
+
},
|
|
161
196
|
};
|
|
162
197
|
}
|