Skip to content

feat(codex): expose personality controls#1009

Open
swear01 wants to merge 5 commits into
tiann:mainfrom
swear01:agent/codex-personality
Open

feat(codex): expose personality controls#1009
swear01 wants to merge 5 commits into
tiann:mainfrom
swear01:agent/codex-personality

Conversation

@swear01

@swear01 swear01 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Closes #1003

Summary

  • add Codex friendly, pragmatic, and none personality state across shared schemas, keepalive, Hub config RPC, REST, and Web mutations
  • expose a Codex-only Personality selector for active remote sessions
  • support /personality query/set/reset commands
  • pass selected personality to Codex app-server thread start/resume and turn parameters
  • preserve Codex config behavior when personality is unset
  • preserve an explicit null/Default override instead of falling back to a persisted selection
  • restore personality through both CLI API session mappers and broadcast keepalive changes to web clients

Why

Codex CLI exposes personality selection and app-server accepts it, but HAPI previously had no remote session state, composer control, slash command, or launcher wiring.

Validation

  • retroactive test-only check on upstream/main: personality config/slash tests failed as expected and the shared catalog export was absent
  • CLI API mapping, personality startup/reset, slash, and app-server config tests — 53 passed
  • Hub alive-event/session route tests — 61 passed, including SSE propagation, select, clear, and local-session rejection
  • shared mode tests — 15 passed
  • repository typecheck passed
  • local non-runner suites passed before the final focused fix: CLI 1103, Hub 453, Web 1131, Shared 106; final changed-area suites were rerun after the fix
  • real-machine smoke with authenticated codex-cli 0.144.1:
    • model/list selected gpt-5.5 with supportsPersonality: true
    • thread start and turn start accepted pragmatic
    • the real model completed a turn
    • thread resume accepted friendly and retained the same thread id
  • follow-up review threads for CLI mapping and SSE propagation resolved in 4eebcec; selector memo refresh resolved in 50e905f
  • git diff --check

@swear01 swear01 marked this pull request as ready for review July 11, 2026 03:52

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Restored personality is dropped before Codex sees it — runCodex now seeds currentPersonality from sessionInfo.personality, but the CLI API mapper still returns only through collaborationMode, so the parsed hub field is discarded before this added line uses it. Resuming an existing Codex session therefore starts with the default personality even when the hub session has friendly/pragmatic/none. Evidence: cli/src/codex/runCodex.ts:98, related mapper context cli/src/api/api.ts:83 and cli/src/api/api.ts:133.
    Suggested fix:

    return {
        ...,
        collaborationMode: raw.collaborationMode,
        personality: raw.personality
    }
  • [Major] Keepalive personality updates are not broadcast to web clients — this branch mutates session.personality, but the session-updated patch emitted below still stops at collaborationMode. Since /personality ... is handled locally and only pushes keepalive, the selector stays stale until a full refetch. Evidence: hub/src/sync/sessionCache.ts:253 and omitted patch field at hub/src/sync/sessionCache.ts:283.
    Suggested fix:

    data: {
        active: true,
        activeAt: session.activeAt,
        thinking: session.thinking,
        permissionMode: session.permissionMode,
        model: session.model,
        modelReasoningEffort: session.modelReasoningEffort,
        effort: session.effort,
        serviceTier: session.serviceTier,
        collaborationMode: session.collaborationMode,
        personality: session.personality
    } satisfies SessionPatch

Questions

  • None.

Summary

  • Review mode: initial
  • Two runtime gaps found: resume drops personality before Codex receives it, and keepalive broadcasts omit personality so web state can become stale.

Testing

  • Not run (automation): bun typecheck failed because bun is not on PATH in this environment. git diff --check passed.

HAPI Bot

Comment thread cli/src/codex/runCodex.ts
Comment thread hub/src/sync/sessionCache.ts

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Minor] Personality selector can render stale state — the memoized overlay now reads personality and onPersonalityChange, but the dependency list was not updated. After changing personality, the session refetch/SSE can update props.session.personality while the open menu keeps showing the old selected option because the overlay memo does not recompute. Evidence: web/src/components/AssistantChat/HappyComposer.tsx:923.
    Suggested fix:
            handleServiceTierChange,
            handleSuggestionSelect,
            personality,
            onPersonalityChange,
            t

Questions

  • None.

Summary

  • Review mode: follow-up after new commits
  • One minor UI state issue found in the new personality menu. The two previous bot findings appear addressed in the follow-up diff.

Testing

  • Not run (automation): bun is not available on PATH, so targeted tests and bun typecheck could not run.
  • git diff --check passed.

HAPI Bot

Comment thread web/src/components/AssistantChat/HappyComposer.tsx

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • None.

Questions

  • None.

Summary

  • Review mode: follow-up after new commits
  • No issues found in the current diff. The previous HAPI Bot memo-dependency finding is addressed in the follow-up commit. Residual risk: I could not run the Bun-based test/typecheck commands in this runner.

Testing

  • Not run (automation): bun is not available on PATH, so bun typecheck and targeted tests could not run.

HAPI Bot

swear01 added a commit to swear01/hapi that referenced this pull request Jul 11, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Personality is dropped when an inactive Codex session is resumed from the web — the new personality config is accepted and cached for active sessions, but resumeSession() still seeds the runner only with model/effort/permission/service tier. After a user selects friendly/pragmatic, lets the session end, then resumes it remotely, the spawned hapi codex resume ... process starts without that personality and the first resumed turn runs with the default. Evidence: hub/src/sync/syncEngine.ts:677 adds personality to the config surface, but the resume spawn path still has no personality argument/payload.
    Suggested fix:
    // hub/src/sync/syncEngine.ts
    await this.rpcGateway.spawnSession(
        targetMachine.id,
        directory,
        flavor,
        session.model ?? undefined,
        session.modelReasoningEffort ?? undefined,
        undefined,
        undefined,
        undefined,
        resumeToken,
        session.effort ?? undefined,
        preferredPermissionMode,
        session.serviceTier ?? undefined,
        session.personality ?? undefined
    )
    
    // also thread `personality` through RpcGateway.spawnSession -> SpawnHappySession
    // -> cli SpawnSessionOptions -> buildCliArgs(`--personality`, value) -> codexCommand -> runCodex.

Questions

  • None.

Summary

  • Review mode: follow-up after new commits
  • Found one resume-path regression in the current full diff. The live active-session RPC path has tests, but the remote resume/runner spawn path needs coverage for carrying personality into the new Codex process.

Testing

  • Not run (automation): review only; did not execute PR code.

HAPI Bot

effort?: string | null
serviceTier?: string | null
collaborationMode?: CodexCollaborationMode
personality?: Session['personality']

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Major] Personality is dropped when an inactive Codex session is resumed from the web. This diff adds personality to the session config surface, but the resume spawn path still seeds the runner only with model/effort/permission/service tier. A user can select friendly/pragmatic, let the session end, and then resume it remotely; the spawned hapi codex resume ... process receives no personality, so the first resumed turn runs with the default.

Suggested fix:

// hub/src/sync/syncEngine.ts
await this.rpcGateway.spawnSession(
    targetMachine.id,
    directory,
    flavor,
    session.model ?? undefined,
    session.modelReasoningEffort ?? undefined,
    undefined,
    undefined,
    undefined,
    resumeToken,
    session.effort ?? undefined,
    preferredPermissionMode,
    session.serviceTier ?? undefined,
    session.personality ?? undefined
)

// also thread `personality` through RpcGateway.spawnSession -> SpawnHappySession
// -> cli SpawnSessionOptions -> buildCliArgs(`--personality`, value) -> codexCommand -> runCodex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(codex): expose CLI personality selection in remote sessions

1 participant