Skip to content

feat: import codex sessions - #1602

Open
curryxjh wants to merge 4 commits into
oceanbase:masterfrom
curryxjh:feat/import-codex-sessions
Open

curryxjh wants to merge 4 commits into
oceanbase:masterfrom
curryxjh:feat/import-codex-sessions

Conversation

@curryxjh

Copy link
Copy Markdown
Contributor

Which issue or RFC does this PR close?

Part of #1300.
Refs #1574.

Closes #.

Rationale for this change

This PR adds the first opt-in import path for pre-install agent session history, starting with Codex. It lets users import historical Codex user prompts as ordinary Content Sources so existing prompt history can participate in PowerContext processing without bypassing the Source pipeline.

The implementation follows the constraints from #1574: Codex-only, explicit/default-off, user prompts only, no assistant replies, no direct Memory writes, no default Scope fallback, and idempotent overlap with live Codex prompt capture.

What changes are included in this PR?

  • Adds powercontext import-sessions --host codex.
  • Reads Codex JSONL session files from CODEX_HOME or ~/.codex.
  • Imports only real user prompts and skips synthetic environment context and assistant messages.
  • Resolves Scope using Codex session/workspace bindings, or imports into --scope-id when provided.
  • Writes prompts through the existing Content Source capture API.
  • Uses the same Codex source identity and metadata shape as the live Codex hook to keep repeated imports and live/import overlap idempotent.
  • Adds --dry-run, --flush, and --checkpoint-file.
  • Records per-item accepted/skipped/failed results and keeps a persistent checkpoint for resume.
  • Skips malformed session files while reporting file-level failures.
  • Updates English and Chinese Sources documentation.
  • Adds focused tests for reader behavior, scope resolution, checkpoint resume, dry-run, bad files, CLI JSON output, and live capture overlap.

Are there any user-facing changes?

Yes. A new explicit CLI command is available:

powercontext import-sessions --host codex

The command is not run automatically. It only imports when the user invokes it. It writes ordinary Content Sources only; Memory extraction is requested only when --flush is passed.
There are no breaking API changes and no changes to existing public persisted formats.

How was this change tested?

Added and updated tests in tests/test_session_import.py.
Commands run:

UV_CACHE_DIR=/private/tmp/powercontext-uv-cache uv run pytest tests/test_session_import.py
UV_CACHE_DIR=/private/tmp/powercontext-uv-cache uv run pytest tests/codex_plugin/test_recall.py -k capture
UV_CACHE_DIR=/private/tmp/powercontext-uv-cache uv run ruff check src/powercontext/client/session_import.py src/powercontext/client/cli.py tests/test_session_import.py
UV_CACHE_DIR=/private/tmp/powercontext-uv-cache uv run ruff format --check src/powercontext/client/session_import.py src/powercontext/client/cli.py tests/test_session_import.py
UV_CACHE_DIR=/private/tmp/powercontext-uv-cache uv run ty check src/powercontext/client/session_import.py src/powercontext/client/cli.py tests/test_session_import.py
UV_CACHE_DIR=/private/tmp/powercontext-uv-cache uv run powercontext import-sessions --help

AI usage statement

Implemented with assistance from OpenAI Codex.

@curryxjh

Copy link
Copy Markdown
Contributor Author

Hardened R8 e2e polling against transient TransportError.

resolved_scope_id = scope_id or await _resolve_codex_scope(client, prompt)
if resolved_scope_id is None:
return _PromptProcessingResult(_item_result(prompt, SessionImportItemStatus.SKIPPED, reason="unresolved_scope"))
source_id = prompt.source_id_for_scope(resolved_scope_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] 修复 redaction 后的 live/import 重叠冲突
这里的 source_id 仍由原始 prompt.content 生成,但下面真正写入的是 redact_known_secrets(prompt.content)。live Codex hook 用同一组 scope_id/session_id/turn_id/prompt 生成相同 source_id,却提交原始 prompt;如果同一 prompt 已被 live capture 写入且包含会被 redaction 替换的 secret,导入器会用同一个 source_id 提交 [REDACTED] 后的不同 content,服务端会返回 409 source_conflict,该项会被记为 capture_failed,与 PR 描述中的 live/import overlap idempotent 不一致。建议让 identity 和实际写入内容使用同一份规范化文本,或显式处理这个 redaction conflict,并补一个“已存在 raw live capture + 导入 redacted prompt”的回归测试。

@Teingi Teingi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed dd2a9635. The 53 focused tests, Ruff checks, and type checks passed. Additional SQLite/HTTP probes and checks against local Codex session formats reproduced the issues below.

Comment thread src/powercontext/client/session_import.py Outdated
Comment thread src/powercontext/client/session_import.py Outdated
Comment thread src/powercontext/client/session_import.py Outdated
Comment thread src/powercontext/client/session_import.py Outdated
if resolved_scope_id is None:
return _PromptProcessingResult(_item_result(prompt, SessionImportItemStatus.SKIPPED, reason="unresolved_scope"))
source_id = prompt.source_id_for_scope(resolved_scope_id)
if _checkpoint_status(checkpoint, source_id) == SessionImportItemStatus.ACCEPTED.value:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] Keep pending flush work separate from capture checkpoints

Accepted checkpoint entries return without adding their Scope to touched_scopes. Importing without --flush and then rerunning with it therefore requests no extraction, despite the CLI suggesting that workflow. The same happens after a flush failure: I injected a 503 after successful capture, and rerunning with --flush made no second flush attempt. Please preserve pending extraction work independently of accepted Source writes so adding or retrying --flush can finish it without recapturing Sources.

Comment thread src/powercontext/client/session_import.py Outdated
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.

3 participants