mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 17:17:38 +00:00
* Require Codex 0.136.0 for native chats
* Add host-owned Codex install and update actions
* Bind Codex checks and maintenance to the selected installation
* Resolve Windows updater cleanup through system helpers
* Use one child environment for Codex checks and launch
* Expire Codex readiness and reconcile current host jobs
* Resolve Codex checks against the child command search path
* Restrict global npm repair to the selected Codex install layout
* Pin the host updater directory through Windows supervision
* Synchronize Codex maintenance fixtures on readiness
* Unify Codex notices and recover version-refused chats
* Route Codex recovery to the operation that remains
* Preserve Codex setup execution errors in the job log
* Preserve UTF-8 in Codex setup logs
* Remove unused Codex host installation detector
* Require host administration for Codex maintenance
* Show a missing Codex explanation once
* test(native-chat): give scripted Codex runtimes their installation fact; keep the registry out of the relay
Runtime tests that drive a scripted Codex app-server still ran the new
version check against whatever codex was on the machine's PATH: refused
on CI (no codex), and on a dev machine it ran the real codex --version.
A scripted transport now must state the Codex it stands for
(readCodexInstallation), asserted at install, and the tests get it from
one scriptedCodexTransport fixture.
The relay's Codex maintenance path reached @orca/windows-registry through
resolvePathEnvKey's re-export in windows-environment-path; import it from
its registry-free module instead.
Also update the catalog-probe test for the shared child environment.
* refactor(native-chat): drop the Update Codex action; keep Install for a missing Codex
A too-old Codex now gets only the plain message ("Codex X is too old for
chats. Update to 0.136.0 or newer.") with no button and no job. The
existing rechecks (window focus, the <=30 s expiry of a saved result)
retry the refused chat once the user has updated Codex themselves.
A missing Codex keeps the Install Codex button: `npm install -g
@openai/codex` with the npm on the chat's PATH, as a host-run job with
its log, then a recheck and recovery. A configured Command that is
missing gets the message only, since a global npm install would not
land at that path.
Removed: the `codex update` command and its 0.126 floor, manual
instructions, npm layout and launcher identity detection, the action
descriptor (install|update) and its titles, the legacy capability, and
the SSH relay maintenance path (structured chat never runs over SSH or
WSL), so the relay preflight handler is back to main's.
* refactor(native-chat): keep Install Codex in Settings only
When Codex isn't installed, main already hides Codex from the New tab menu,
so the in-chat Install button was almost never reachable. Settings → Agents
already shows "Codex isn't installed." with Install Codex.
- Chats and the new-workspace composer now only state "Codex isn't
installed." (no button, no install job from the chat).
- The Install action, its busy spinner and the host-busy subscription move
into the Settings Codex row, the only place that starts the job.
- The store no longer re-checks every other workspace context when a job
finishes. A refused chat recovers through the same re-check a too-old
Codex uses (window focus, or the <=30 s expiry of a saved result).
- The chat recovery key no longer includes the install job id.
- Tests: Settings drives the install; a new test proves a chat refused for
a missing Codex recovers through focus after a Settings install, not
through the job; the expiry recovery test covers missing and too old.
* refactor(codex): check chat compatibility when acquiring the child
* Restore workspace submit guard and simplify Codex maintenance
* Keep only the Codex chat minimum version
62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import {
|
|
readWholeAgentSessionFailureFact,
|
|
type AgentSessionFailureFact
|
|
} from './agent-session-failure'
|
|
import type { AgentJournalRenderItem } from './agent-session-journal-types'
|
|
import { isStructuredAgentSessionStartFailureRow } from './structured-agent-session-start-failure-row-key'
|
|
|
|
/** Loaded startup causes and authentication explanations already visible in the transcript. */
|
|
export function agentSessionVisibleFailureFacts(
|
|
items: readonly AgentJournalRenderItem[]
|
|
): AgentSessionFailureFact[] {
|
|
const facts: AgentSessionFailureFact[] = []
|
|
for (const item of items) {
|
|
if (item.body.kind === 'status') {
|
|
const fact = readWholeAgentSessionFailureFact(item.body.failure)
|
|
if (
|
|
fact &&
|
|
(isStructuredAgentSessionStartFailureRow(item.itemId) || fact.kind === 'notSignedIn')
|
|
) {
|
|
facts.push(fact)
|
|
}
|
|
}
|
|
}
|
|
return facts
|
|
}
|
|
|
|
/** Whether two facts are one failure: a start's row and the messages it rejected share one. */
|
|
export function sameAgentSessionFailureFact(
|
|
a: AgentSessionFailureFact,
|
|
b: AgentSessionFailureFact
|
|
): boolean {
|
|
return (
|
|
a.kind === b.kind &&
|
|
a.account === b.account &&
|
|
a.detail?.text === b.detail?.text &&
|
|
a.detail?.audience === b.detail?.audience &&
|
|
a.refusal?.code === b.refusal?.code &&
|
|
a.refusal?.details?.reason === b.refusal?.details?.reason &&
|
|
(a.refusal?.code !== 'agent_session_operation_invalid' ||
|
|
b.refusal?.code !== 'agent_session_operation_invalid' ||
|
|
(a.refusal.details?.codexInstallation?.installedVersion ===
|
|
b.refusal.details?.codexInstallation?.installedVersion &&
|
|
a.refusal.details?.codexInstallation?.minimumVersion ===
|
|
b.refusal.details?.codexInstallation?.minimumVersion)) &&
|
|
a.attachment?.reason === b.attachment?.reason &&
|
|
a.attachment?.limit === b.attachment?.limit &&
|
|
a.retry?.error === b.retry?.error &&
|
|
a.retry?.status === b.retry?.status
|
|
)
|
|
}
|
|
|
|
/** Whether a loaded row already states this failure, comparing facts rather than wording. */
|
|
export function agentSessionFailureStatedByRow(
|
|
failure: unknown,
|
|
statedFailures: readonly AgentSessionFailureFact[]
|
|
): boolean {
|
|
const fact = readWholeAgentSessionFailureFact(failure)
|
|
return (
|
|
fact !== undefined && statedFailures.some((stated) => sameAgentSessionFailureFact(stated, fact))
|
|
)
|
|
}
|