mirror of
https://github.com/openai/codex.git
synced 2026-05-06 12:26:38 +00:00
Compare commits
153 Commits
lt/integra
...
vb/windows
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19bddf304c | ||
|
|
fa127be25f | ||
|
|
54d1401170 | ||
|
|
b7c0f26910 | ||
|
|
431ebeaef7 | ||
|
|
fd36838cf3 | ||
|
|
803705f795 | ||
|
|
7d72fc8f53 | ||
|
|
b985768dc1 | ||
|
|
0a32c8b396 | ||
|
|
341550c275 | ||
|
|
92fb848065 | ||
|
|
fc2a69107c | ||
|
|
bf38def44e | ||
|
|
5ba908d179 | ||
|
|
b7e5588d18 | ||
|
|
6a8df2b61d | ||
|
|
c08177f7d0 | ||
|
|
2307aa8d98 | ||
|
|
af95662a70 | ||
|
|
4e05f3053c | ||
|
|
7e8594fc19 | ||
|
|
a3350de855 | ||
|
|
2f3b5ed81a | ||
|
|
755880ef9c | ||
|
|
c5a495c2cd | ||
|
|
dcd139b7c4 | ||
|
|
e64c765673 | ||
|
|
e903d000b0 | ||
|
|
739ab6bc51 | ||
|
|
30c5c768de | ||
|
|
2be9fd5a93 | ||
|
|
0f40261e86 | ||
|
|
4ded800374 | ||
|
|
5c30d79afb | ||
|
|
798de22637 | ||
|
|
c5e2921e1d | ||
|
|
4b55979755 | ||
|
|
52c06b8759 | ||
|
|
0bd25ab374 | ||
|
|
850f035b8c | ||
|
|
277186ec85 | ||
|
|
215d5a8f7c | ||
|
|
85c1500569 | ||
|
|
e5709db6dc | ||
|
|
cafe717dca | ||
|
|
c2084552d9 | ||
|
|
2009f6e894 | ||
|
|
4ed22fc7d2 | ||
|
|
48dd7b58f0 | ||
|
|
0e2300c02c | ||
|
|
6c51bf0c7c | ||
|
|
bb83eec825 | ||
|
|
f431ec12c9 | ||
|
|
79b4f691a6 | ||
|
|
5d314f324c | ||
|
|
01ab25dbb5 | ||
|
|
a37adea0db | ||
|
|
f8c527e529 | ||
|
|
4f1d5f00f0 | ||
|
|
a6ca39c630 | ||
|
|
523e4aa8e3 | ||
|
|
0ccd659b4b | ||
|
|
8033b6a449 | ||
|
|
0d8cdc0510 | ||
|
|
c3e60849e5 | ||
|
|
ad57a3fee2 | ||
|
|
1f304dd1f2 | ||
|
|
2cb8746457 | ||
|
|
35bc6e3d01 | ||
|
|
0bda8161a2 | ||
|
|
4c58e64f08 | ||
|
|
ba159cbc79 | ||
|
|
dda8199b73 | ||
|
|
9c3abcd46c | ||
|
|
2a020f1a0a | ||
|
|
deaa307fb2 | ||
|
|
4d7ce3447d | ||
|
|
fed0a8f4fa | ||
|
|
ac2bffa443 | ||
|
|
87bc72408c | ||
|
|
355c40ad7e | ||
|
|
5591912f0b | ||
|
|
4e30281a13 | ||
|
|
9881dc7306 | ||
|
|
d54493ba1c | ||
|
|
9aaa5d9358 | ||
|
|
0c785598b3 | ||
|
|
f41306b4f3 | ||
|
|
bce74c70ce | ||
|
|
88f300d74d | ||
|
|
022f81df1f | ||
|
|
706490ab1b | ||
|
|
6e838a19fa | ||
|
|
a2db6f97fb | ||
|
|
f5497f4d65 | ||
|
|
f1c963d77e | ||
|
|
4167628622 | ||
|
|
32ace07ac5 | ||
|
|
6c874f9b34 | ||
|
|
0ee737cea6 | ||
|
|
8a559e7938 | ||
|
|
cf02e9c052 | ||
|
|
1c3287125f | ||
|
|
789f387982 | ||
|
|
d19de6d150 | ||
|
|
5378cccd8a | ||
|
|
32aad7bd13 | ||
|
|
219c65dc2f | ||
|
|
1e560f33e1 | ||
|
|
588f7a9fc4 | ||
|
|
3c6e2638ac | ||
|
|
9b8a1fbefc | ||
|
|
6de6eaa0c1 | ||
|
|
c43e2fcfbf | ||
|
|
db94b1657b | ||
|
|
0a9b559c0b | ||
|
|
13e0ec1614 | ||
|
|
7262c0c450 | ||
|
|
687c5d9081 | ||
|
|
a3cccbd8ed | ||
|
|
0db6811b7c | ||
|
|
dee5f5ea38 | ||
|
|
6bb2fa3fd4 | ||
|
|
e787358f70 | ||
|
|
bcc1caa920 | ||
|
|
f802f0a391 | ||
|
|
11806faf71 | ||
|
|
28742866c7 | ||
|
|
deb4509302 | ||
|
|
9eadff9713 | ||
|
|
120aa07d81 | ||
|
|
21463a5074 | ||
|
|
c10f95ddac | ||
|
|
ddfa691752 | ||
|
|
6f87eb0479 | ||
|
|
e083b6c757 | ||
|
|
ac8c9fc49c | ||
|
|
b68366718b | ||
|
|
d87d918716 | ||
|
|
4816b89204 | ||
|
|
33cc135cc3 | ||
|
|
19badb0be2 | ||
|
|
e8d8080818 | ||
|
|
53be451673 | ||
|
|
a9c111da54 | ||
|
|
49fb25997f | ||
|
|
e3c8720a99 | ||
|
|
432771c5fd | ||
|
|
72f757d144 | ||
|
|
5882f3f95e | ||
|
|
a9f75e5cda | ||
|
|
867820ac7e |
1
.bazelrc
1
.bazelrc
@@ -29,7 +29,6 @@ common:linux --test_env=PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
||||
common:macos --test_env=PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
||||
|
||||
# Pass through some env vars Windows needs to use powershell?
|
||||
common:windows --test_env=PATH
|
||||
common:windows --test_env=SYSTEMROOT
|
||||
common:windows --test_env=COMSPEC
|
||||
common:windows --test_env=WINDIR
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[codespell]
|
||||
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
|
||||
skip = .git*,vendor,*-lock.yaml,*.lock,.codespellrc,*test.ts,*.jsonl,frame*.txt,*.snap,*.snap.new,*meriyah.umd.min.js
|
||||
skip = .git*,vendor,*-lock.yaml,*.lock,.codespellrc,*test.ts,*.jsonl,frame*.txt,*.snap,*.snap.new
|
||||
check-hidden = true
|
||||
ignore-regex = ^\s*"image/\S+": ".*|\b(afterAll)\b
|
||||
ignore-words-list = ratatui,ser,iTerm,iterm2,iterm,te,TE,PASE,SEH
|
||||
|
||||
102
.codex/skills/codex-issue-digest/SKILL.md
Normal file
102
.codex/skills/codex-issue-digest/SKILL.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
name: codex-issue-digest
|
||||
description: Run a GitHub issue digest for openai/codex by feature-area labels, all areas, and configurable time windows. Use when asked to summarize recent Codex bug reports or enhancement requests, especially for owner-specific labels such as tui, exec, app, or similar areas.
|
||||
---
|
||||
|
||||
# Codex Issue Digest
|
||||
|
||||
## Objective
|
||||
|
||||
Produce a concise, insight-oriented digest of `openai/codex` issues for the requested feature-area labels over the previous 24 hours by default. Honor a different duration when the user asks for one, for example "past week" or "48 hours".
|
||||
|
||||
Include only issues that currently have `bug` or `enhancement` plus at least one requested owner label. If the user asks for all areas or all labels, collect `bug`/`enhancement` issues across all labels.
|
||||
|
||||
## Inputs
|
||||
|
||||
- Feature-area labels, for example `tui exec`
|
||||
- `all areas` / `all labels` to scan all current feature labels
|
||||
- Optional repo override, default `openai/codex`
|
||||
- Optional time window, default previous 24 hours; examples: `48h`, `7d`, `1w`, `past week`
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Run the collector from a current Codex repo checkout:
|
||||
|
||||
```bash
|
||||
python3 .codex/skills/codex-issue-digest/scripts/collect_issue_digest.py --labels tui exec --window-hours 24
|
||||
```
|
||||
|
||||
Use `--window "past week"` or `--window-hours 168` when the user asks for a non-default duration. Use `--all-labels` when the user says all areas or all labels.
|
||||
|
||||
2. Use the JSON as the source of truth. It includes new issues, new issue comments, new reactions/upvotes, current labels, current reaction counts, model-ready `summary_inputs`, and detailed `digest_rows`.
|
||||
3. Start the report with `## Summary`, then `## Details`.
|
||||
4. In `## Summary`, write skim-first headlines:
|
||||
- Lead with the most important fact or judgment. Do not start with aggregate counts unless the aggregate itself is the story.
|
||||
- Make the first 1-3 bullets answer "what should owners pay attention to right now?"
|
||||
- Bold only the critical insight phrase in each high-priority bullet, for example `**GPT-5.5 context is the dominant pressure point**`.
|
||||
- Keep summary bullets short enough to scan in about 20 seconds.
|
||||
- Put broad stats near the end of the summary, after the owner-relevant takeaways.
|
||||
- Say clearly when there is nothing significant to act on.
|
||||
- Call out any areas or themes receiving lots of user attention.
|
||||
- Cluster and name themes yourself from `summary_inputs`; the collector intentionally does not hard-code issue categories.
|
||||
- Use a cluster only when the issues genuinely share the same product problem. If several issues merely share a broad platform or label, describe them individually.
|
||||
- Do not omit a repeated theme just because its individual issues fall below the details table cutoff. Several similar reports should be called out as a repeated customer concern.
|
||||
- For single-issue rows, summarize the concern directly instead of calling it a cluster.
|
||||
- Use inline numbered issue links from each relevant row's `ref_markdown`.
|
||||
5. In `## Details`, include a compact table only when useful:
|
||||
- Prefer rows from `digest_rows`; include a `Refs` column using each row's `ref_markdown`.
|
||||
- Keep the table short; omit low-signal rows when the summary already covers them.
|
||||
- Use compact columns such as marker, area, type, description, interactions, and refs.
|
||||
- The `Description` cell should be a short owner-readable phrase. Use row `description`, title, body excerpts, and recent comments, but do not mechanically copy the raw GitHub issue title when it contains incidental details.
|
||||
- A clear quiet/no-concern sentence when there is no meaningful signal.
|
||||
6. Use the JSON `attention_marker` exactly. It is empty for normal rows, `🔥` for elevated rows, and `🔥🔥` for very high-attention rows. The actual cutoffs are in `attention_thresholds`.
|
||||
7. Use inline numbered references where a row or bullet points to issues, for example `Compaction bugs [1](https://github.com/openai/codex/issues/123), [2](https://github.com/openai/codex/issues/456)`. Do not add a separate footnotes section.
|
||||
8. Label `interactions` as `Interactions`; it counts posts/comments/reactions during the requested window, not unique people.
|
||||
9. Mention the collector `script_version`, repo checkout `git_head`, and time window in the digest footer or final line.
|
||||
|
||||
## Reaction Handling
|
||||
|
||||
The collector uses GitHub reactions endpoints, which include `created_at`, to count reactions created during the digest window for hydrated issues. It reports both in-window reaction counts and current reaction totals. Treat current reaction totals as standing engagement, and treat `new_reactions` / `new_upvotes` as windowed activity.
|
||||
|
||||
By default, the collector fetches issue comments with `since=<window start>` and caps the number of comment pages per issue. This keeps very long historical threads from dominating a digest run and focuses the report on recent posts. Use `--fetch-all-comments` only when exhaustive comment history is more important than runtime.
|
||||
|
||||
GitHub issue search is still seeded by issue `updated_at`, so a purely reaction-only issue may be missed if reactions do not bump `updated_at`. Covering every reaction-only case would require either a persisted snapshot store or a broader scan of labeled issues.
|
||||
|
||||
## Attention Markers
|
||||
|
||||
The collector scales attention markers by the requested time window. The baseline is 10 human user interactions for `🔥` and 20 for `🔥🔥` over 24 hours; longer or shorter windows scale those cutoffs linearly and round up. For example, a one-week report uses 70 and 140 interactions. Human user interactions are human-authored new issue posts, human-authored new comments, and human reactions created during the window, including upvotes. Bot posts and bot reactions are excluded. In prose, explain this as high user interaction rather than naming the emoji.
|
||||
|
||||
## Freshness
|
||||
|
||||
The automation should run from a repo checkout that contains this skill. For shared daily use, prefer one of these patterns:
|
||||
|
||||
- Run the automation in a checkout that is refreshed before the automation starts, for example with `git pull --ff-only`.
|
||||
- If the automation cannot safely mutate the checkout, have it report the current `git_head` from the collector output so readers know which skill/script version produced the digest.
|
||||
|
||||
## Sample Owner Prompt
|
||||
|
||||
```text
|
||||
Use $codex-issue-digest to run the Codex issue digest for labels tui and exec over the previous 24 hours.
|
||||
```
|
||||
|
||||
```text
|
||||
Use $codex-issue-digest to run the Codex issue digest for all areas over the past week.
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Dry run the collector against recent issues:
|
||||
|
||||
```bash
|
||||
python3 .codex/skills/codex-issue-digest/scripts/collect_issue_digest.py --labels tui exec --window-hours 24
|
||||
```
|
||||
|
||||
```bash
|
||||
python3 .codex/skills/codex-issue-digest/scripts/collect_issue_digest.py --all-labels --window "past week" --limit-issues 10
|
||||
```
|
||||
|
||||
Run the focused script tests:
|
||||
|
||||
```bash
|
||||
pytest .codex/skills/codex-issue-digest/scripts/test_collect_issue_digest.py
|
||||
```
|
||||
4
.codex/skills/codex-issue-digest/agents/openai.yaml
Normal file
4
.codex/skills/codex-issue-digest/agents/openai.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Codex Issue Digest"
|
||||
short_description: "Summarize Codex issues by labels or all areas"
|
||||
default_prompt: "Use $codex-issue-digest to run the Codex issue digest for labels tui and exec over the previous 24 hours."
|
||||
988
.codex/skills/codex-issue-digest/scripts/collect_issue_digest.py
Executable file
988
.codex/skills/codex-issue-digest/scripts/collect_issue_digest.py
Executable file
@@ -0,0 +1,988 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Collect recent openai/codex issue activity for owner-focused digests."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import math
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
|
||||
SCRIPT_VERSION = 2
|
||||
QUALIFYING_KIND_LABELS = ("bug", "enhancement")
|
||||
REACTION_KEYS = ("+1", "-1", "laugh", "hooray", "confused", "heart", "rocket", "eyes")
|
||||
BASE_ATTENTION_WINDOW_HOURS = 24.0
|
||||
ONE_ATTENTION_INTERACTION_THRESHOLD = 10
|
||||
TWO_ATTENTION_INTERACTION_THRESHOLD = 20
|
||||
ALL_LABEL_PHRASES = {"all", "all areas", "all labels", "all-areas", "all-labels", "*"}
|
||||
|
||||
|
||||
class GhCommandError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Collect recent GitHub issue activity for a Codex owner digest."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--repo", default="openai/codex", help="OWNER/REPO, default openai/codex"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--labels",
|
||||
nargs="+",
|
||||
default=[],
|
||||
help="Feature-area labels owned by the digest recipient, for example: tui exec",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--all-labels",
|
||||
action="store_true",
|
||||
help="Collect bug/enhancement issues across all feature-area labels",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--window",
|
||||
help='Lookback duration such as "24h", "7d", "1w", or "past week"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--window-hours", type=float, default=24.0, help="Lookback window"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--since", help="UTC ISO timestamp override for the window start"
|
||||
)
|
||||
parser.add_argument("--until", help="UTC ISO timestamp override for the window end")
|
||||
parser.add_argument(
|
||||
"--limit-issues",
|
||||
type=int,
|
||||
default=200,
|
||||
help="Maximum candidate issues to hydrate after search",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--body-chars", type=int, default=1200, help="Issue body excerpt length"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--comment-chars", type=int, default=900, help="Comment excerpt length"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--max-comment-pages",
|
||||
type=int,
|
||||
default=3,
|
||||
help=(
|
||||
"Maximum pages of issue comments to hydrate per issue after applying the "
|
||||
"window filter. Use 0 with --fetch-all-comments for no page cap."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--fetch-all-comments",
|
||||
action="store_true",
|
||||
help="Hydrate complete issue comment histories instead of only window-updated comments.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def parse_timestamp(value, arg_name):
|
||||
if value is None:
|
||||
return None
|
||||
normalized = value.strip()
|
||||
if not normalized:
|
||||
return None
|
||||
if normalized.endswith("Z"):
|
||||
normalized = f"{normalized[:-1]}+00:00"
|
||||
try:
|
||||
parsed = datetime.fromisoformat(normalized)
|
||||
except ValueError as err:
|
||||
raise ValueError(f"{arg_name} must be an ISO timestamp") from err
|
||||
if parsed.tzinfo is None:
|
||||
parsed = parsed.replace(tzinfo=timezone.utc)
|
||||
return parsed.astimezone(timezone.utc)
|
||||
|
||||
|
||||
def format_timestamp(value):
|
||||
return (
|
||||
value.astimezone(timezone.utc)
|
||||
.replace(microsecond=0)
|
||||
.isoformat()
|
||||
.replace("+00:00", "Z")
|
||||
)
|
||||
|
||||
|
||||
def resolve_window(args):
|
||||
until = parse_timestamp(args.until, "--until") or datetime.now(timezone.utc)
|
||||
since = parse_timestamp(args.since, "--since")
|
||||
if since is None:
|
||||
hours = parse_duration_hours(getattr(args, "window", None))
|
||||
if hours is None:
|
||||
hours = getattr(args, "window_hours", 24.0)
|
||||
if hours <= 0:
|
||||
raise ValueError("window duration must be > 0")
|
||||
since = until - timedelta(hours=hours)
|
||||
if since >= until:
|
||||
raise ValueError("--since must be before --until")
|
||||
return since, until
|
||||
|
||||
|
||||
def parse_duration_hours(value):
|
||||
if value is None:
|
||||
return None
|
||||
text = value.strip().casefold().replace("_", " ")
|
||||
if not text:
|
||||
return None
|
||||
text = re.sub(r"^(past|last)\s+", "", text)
|
||||
aliases = {
|
||||
"day": 24.0,
|
||||
"24h": 24.0,
|
||||
"week": 168.0,
|
||||
"7d": 168.0,
|
||||
}
|
||||
if text in aliases:
|
||||
return aliases[text]
|
||||
match = re.fullmatch(r"(\d+(?:\.\d+)?)\s*(h|hr|hrs|hour|hours)", text)
|
||||
if match:
|
||||
return float(match.group(1))
|
||||
match = re.fullmatch(r"(\d+(?:\.\d+)?)\s*(d|day|days)", text)
|
||||
if match:
|
||||
return float(match.group(1)) * 24.0
|
||||
match = re.fullmatch(r"(\d+(?:\.\d+)?)\s*(w|week|weeks)", text)
|
||||
if match:
|
||||
return float(match.group(1)) * 168.0
|
||||
raise ValueError(f"Unsupported duration: {value}")
|
||||
|
||||
|
||||
def normalize_requested_labels(labels, all_labels=False):
|
||||
out = []
|
||||
seen = set()
|
||||
for raw in labels:
|
||||
for piece in raw.split(","):
|
||||
label = piece.strip()
|
||||
if not label:
|
||||
continue
|
||||
key = label.casefold()
|
||||
if key not in seen:
|
||||
out.append(label)
|
||||
seen.add(key)
|
||||
phrase = " ".join(label.casefold() for label in out)
|
||||
if all_labels or phrase in ALL_LABEL_PHRASES:
|
||||
return [], True
|
||||
if not out:
|
||||
raise ValueError(
|
||||
"At least one feature-area label is required, or use --all-labels"
|
||||
)
|
||||
return out, False
|
||||
|
||||
|
||||
def quote_label(label):
|
||||
if re.fullmatch(r"[A-Za-z0-9_.:-]+", label):
|
||||
return f"label:{label}"
|
||||
escaped = label.replace('"', '\\"')
|
||||
return f'label:"{escaped}"'
|
||||
|
||||
|
||||
def build_search_queries(
|
||||
repo, owner_labels, since, kind_labels=QUALIFYING_KIND_LABELS, all_labels=False
|
||||
):
|
||||
since_date = since.date().isoformat()
|
||||
queries = []
|
||||
if all_labels:
|
||||
for kind_label in kind_labels:
|
||||
queries.append(
|
||||
" ".join(
|
||||
[
|
||||
f"repo:{repo}",
|
||||
"is:issue",
|
||||
f"updated:>={since_date}",
|
||||
quote_label(kind_label),
|
||||
]
|
||||
)
|
||||
)
|
||||
return queries
|
||||
for owner_label in owner_labels:
|
||||
for kind_label in kind_labels:
|
||||
queries.append(
|
||||
" ".join(
|
||||
[
|
||||
f"repo:{repo}",
|
||||
"is:issue",
|
||||
f"updated:>={since_date}",
|
||||
quote_label(owner_label),
|
||||
quote_label(kind_label),
|
||||
]
|
||||
)
|
||||
)
|
||||
return queries
|
||||
|
||||
|
||||
def _format_gh_error(cmd, err):
|
||||
stdout = (err.stdout or "").strip()
|
||||
stderr = (err.stderr or "").strip()
|
||||
parts = [f"GitHub CLI command failed: {' '.join(cmd)}"]
|
||||
if stdout:
|
||||
parts.append(f"stdout: {stdout}")
|
||||
if stderr:
|
||||
parts.append(f"stderr: {stderr}")
|
||||
return "\n".join(parts)
|
||||
|
||||
|
||||
def gh_json(args):
|
||||
cmd = ["gh", *args]
|
||||
try:
|
||||
proc = subprocess.run(cmd, check=True, capture_output=True, text=True)
|
||||
except FileNotFoundError as err:
|
||||
raise GhCommandError("`gh` command not found") from err
|
||||
except subprocess.CalledProcessError as err:
|
||||
raise GhCommandError(_format_gh_error(cmd, err)) from err
|
||||
raw = proc.stdout.strip()
|
||||
if not raw:
|
||||
return None
|
||||
try:
|
||||
return json.loads(raw)
|
||||
except json.JSONDecodeError as err:
|
||||
raise GhCommandError(
|
||||
f"Failed to parse JSON from gh output for {' '.join(args)}"
|
||||
) from err
|
||||
|
||||
|
||||
def gh_text(args):
|
||||
cmd = ["gh", *args]
|
||||
try:
|
||||
proc = subprocess.run(cmd, check=True, capture_output=True, text=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
return ""
|
||||
return proc.stdout.strip()
|
||||
|
||||
|
||||
def git_head():
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["git", "rev-parse", "--short=12", "HEAD"],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
return None
|
||||
return proc.stdout.strip() or None
|
||||
|
||||
|
||||
def skill_relative_path():
|
||||
try:
|
||||
return str(Path(__file__).resolve().relative_to(Path.cwd().resolve()))
|
||||
except ValueError:
|
||||
return str(Path(__file__).resolve())
|
||||
|
||||
|
||||
def gh_api_list_paginated(endpoint, per_page=100, max_pages=None, with_metadata=False):
|
||||
items = []
|
||||
page = 1
|
||||
truncated = False
|
||||
while True:
|
||||
sep = "&" if "?" in endpoint else "?"
|
||||
page_endpoint = f"{endpoint}{sep}per_page={per_page}&page={page}"
|
||||
payload = gh_json(["api", page_endpoint])
|
||||
if payload is None:
|
||||
break
|
||||
if not isinstance(payload, list):
|
||||
raise GhCommandError(f"Unexpected paginated payload from gh api {endpoint}")
|
||||
items.extend(payload)
|
||||
if len(payload) < per_page:
|
||||
break
|
||||
if max_pages is not None and page >= max_pages:
|
||||
truncated = True
|
||||
break
|
||||
page += 1
|
||||
if with_metadata:
|
||||
return {
|
||||
"items": items,
|
||||
"truncated": truncated,
|
||||
"pages": page,
|
||||
"max_pages": max_pages,
|
||||
}
|
||||
return items
|
||||
|
||||
|
||||
def search_issue_numbers(queries, limit):
|
||||
numbers = {}
|
||||
for query in queries:
|
||||
page = 1
|
||||
while True:
|
||||
payload = gh_json(
|
||||
[
|
||||
"api",
|
||||
"search/issues",
|
||||
"-X",
|
||||
"GET",
|
||||
"-f",
|
||||
f"q={query}",
|
||||
"-f",
|
||||
"per_page=100",
|
||||
"-f",
|
||||
f"page={page}",
|
||||
]
|
||||
)
|
||||
if not isinstance(payload, dict):
|
||||
raise GhCommandError("Unexpected payload from GitHub issue search")
|
||||
items = payload.get("items") or []
|
||||
if not isinstance(items, list):
|
||||
raise GhCommandError("Expected search `items` to be a list")
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
number = item.get("number")
|
||||
if isinstance(number, int):
|
||||
numbers[number] = str(item.get("updated_at") or "")
|
||||
if len(items) < 100 or len(numbers) >= limit:
|
||||
break
|
||||
page += 1
|
||||
ordered = sorted(
|
||||
numbers, key=lambda number: (numbers[number], number), reverse=True
|
||||
)
|
||||
return ordered[:limit]
|
||||
|
||||
|
||||
def fetch_issue(repo, number):
|
||||
payload = gh_json(["api", f"repos/{repo}/issues/{number}"])
|
||||
if not isinstance(payload, dict):
|
||||
raise GhCommandError(f"Unexpected issue payload for #{number}")
|
||||
return payload
|
||||
|
||||
|
||||
def fetch_comments(repo, number, since=None, max_pages=None):
|
||||
endpoint = f"repos/{repo}/issues/{number}/comments"
|
||||
if since is not None:
|
||||
endpoint = f"{endpoint}?since={quote(format_timestamp(since), safe='')}"
|
||||
return gh_api_list_paginated(
|
||||
endpoint,
|
||||
max_pages=max_pages,
|
||||
with_metadata=True,
|
||||
)
|
||||
|
||||
|
||||
def fetch_reactions_for_item(endpoint, item):
|
||||
if reaction_summary(item)["total"] <= 0:
|
||||
return []
|
||||
return gh_api_list_paginated(endpoint)
|
||||
|
||||
|
||||
def fetch_comment_reactions(repo, comments):
|
||||
reactions_by_comment_id = {}
|
||||
for comment in comments:
|
||||
comment_id = comment.get("id")
|
||||
if comment_id in (None, ""):
|
||||
continue
|
||||
endpoint = f"repos/{repo}/issues/comments/{comment_id}/reactions"
|
||||
reactions_by_comment_id[comment_id] = fetch_reactions_for_item(
|
||||
endpoint, comment
|
||||
)
|
||||
return reactions_by_comment_id
|
||||
|
||||
|
||||
def extract_login(user_obj):
|
||||
if isinstance(user_obj, dict):
|
||||
return str(user_obj.get("login") or "")
|
||||
return ""
|
||||
|
||||
|
||||
def is_bot_login(login):
|
||||
return bool(login) and login.lower().endswith("[bot]")
|
||||
|
||||
|
||||
def is_human_user(user_obj):
|
||||
login = extract_login(user_obj)
|
||||
return bool(login) and not is_bot_login(login)
|
||||
|
||||
|
||||
def label_names(issue):
|
||||
labels = []
|
||||
for label in issue.get("labels") or []:
|
||||
if isinstance(label, dict) and label.get("name"):
|
||||
labels.append(str(label["name"]))
|
||||
return sorted(labels, key=str.casefold)
|
||||
|
||||
|
||||
def matching_labels(labels, requested):
|
||||
labels_by_key = {label.casefold(): label for label in labels}
|
||||
return [label for label in requested if label.casefold() in labels_by_key]
|
||||
|
||||
|
||||
def area_labels(labels):
|
||||
kind_keys = {label.casefold() for label in QUALIFYING_KIND_LABELS}
|
||||
return [label for label in labels if label.casefold() not in kind_keys]
|
||||
|
||||
|
||||
def attention_thresholds_for_window(window_hours):
|
||||
if window_hours <= 0:
|
||||
raise ValueError("window_hours must be > 0")
|
||||
window_hours = round(window_hours, 6)
|
||||
scale = window_hours / BASE_ATTENTION_WINDOW_HOURS
|
||||
elevated = max(1, math.ceil(ONE_ATTENTION_INTERACTION_THRESHOLD * scale))
|
||||
very_high = max(
|
||||
elevated + 1, math.ceil(TWO_ATTENTION_INTERACTION_THRESHOLD * scale)
|
||||
)
|
||||
return {
|
||||
"base_window_hours": BASE_ATTENTION_WINDOW_HOURS,
|
||||
"window_hours": round(window_hours, 3),
|
||||
"scale": round(scale, 3),
|
||||
"elevated": elevated,
|
||||
"very_high": very_high,
|
||||
}
|
||||
|
||||
|
||||
def attention_level_for(user_interactions, attention_thresholds=None):
|
||||
thresholds = attention_thresholds or attention_thresholds_for_window(
|
||||
BASE_ATTENTION_WINDOW_HOURS
|
||||
)
|
||||
if user_interactions >= thresholds["very_high"]:
|
||||
return 2
|
||||
if user_interactions >= thresholds["elevated"]:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def attention_marker_for(user_interactions, attention_thresholds=None):
|
||||
return "🔥" * attention_level_for(user_interactions, attention_thresholds)
|
||||
|
||||
|
||||
def reaction_summary(item):
|
||||
reactions = item.get("reactions")
|
||||
if not isinstance(reactions, dict):
|
||||
return {"total": 0, "counts": {}}
|
||||
counts = {}
|
||||
for key in REACTION_KEYS:
|
||||
value = reactions.get(key, 0)
|
||||
if isinstance(value, int) and value:
|
||||
counts[key] = value
|
||||
total = reactions.get("total_count")
|
||||
if not isinstance(total, int):
|
||||
total = sum(counts.values())
|
||||
return {"total": total, "counts": counts}
|
||||
|
||||
|
||||
def reaction_event_summary(reactions, since, until):
|
||||
counts = {}
|
||||
total = 0
|
||||
for reaction in reactions or []:
|
||||
if not isinstance(reaction, dict):
|
||||
continue
|
||||
if not is_in_window(str(reaction.get("created_at") or ""), since, until):
|
||||
continue
|
||||
if not is_human_user(reaction.get("user")):
|
||||
continue
|
||||
content = str(reaction.get("content") or "")
|
||||
if not content:
|
||||
continue
|
||||
counts[content] = counts.get(content, 0) + 1
|
||||
total += 1
|
||||
return {
|
||||
"total": total,
|
||||
"counts": counts,
|
||||
"upvotes": counts.get("+1", 0),
|
||||
}
|
||||
|
||||
|
||||
def compact_text(value, limit):
|
||||
text = re.sub(r"\s+", " ", str(value or "")).strip()
|
||||
if limit <= 0:
|
||||
return ""
|
||||
if len(text) <= limit:
|
||||
return text
|
||||
return f"{text[: max(limit - 1, 0)].rstrip()}..."
|
||||
|
||||
|
||||
def clean_title_for_description(title):
|
||||
cleaned = re.sub(r"\s+", " ", str(title or "")).strip()
|
||||
cleaned = re.sub(
|
||||
r"^(codex(?: desktop| app|\.app| cli)?|desktop|windows codex app)\s*[:,-]\s*",
|
||||
"",
|
||||
cleaned,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
cleaned = re.sub(r"^on windows,\s*", "Windows: ", cleaned, flags=re.IGNORECASE)
|
||||
cleaned = cleaned.strip(" -:;")
|
||||
return compact_text(cleaned, 80) or "Issue needs owner review"
|
||||
|
||||
|
||||
def issue_description(issue):
|
||||
return clean_title_for_description(issue.get("title"))
|
||||
|
||||
|
||||
def is_in_window(timestamp, since, until):
|
||||
parsed = parse_timestamp(timestamp, "timestamp")
|
||||
if parsed is None:
|
||||
return False
|
||||
return since <= parsed < until
|
||||
|
||||
|
||||
def summarize_comment(
|
||||
comment, comment_chars, reaction_events=None, since=None, until=None
|
||||
):
|
||||
reactions = reaction_summary(comment)
|
||||
new_reactions = (
|
||||
reaction_event_summary(reaction_events, since, until)
|
||||
if since is not None and until is not None
|
||||
else {"total": 0, "counts": {}, "upvotes": 0}
|
||||
)
|
||||
human_user_interaction = is_human_user(comment.get("user"))
|
||||
return {
|
||||
"id": comment.get("id"),
|
||||
"author": extract_login(comment.get("user")),
|
||||
"author_association": str(comment.get("author_association") or ""),
|
||||
"created_at": str(comment.get("created_at") or ""),
|
||||
"updated_at": str(comment.get("updated_at") or ""),
|
||||
"url": str(comment.get("html_url") or ""),
|
||||
"human_user_interaction": human_user_interaction,
|
||||
"reactions": reactions["counts"],
|
||||
"reaction_total": reactions["total"],
|
||||
"new_reactions": new_reactions["total"],
|
||||
"new_upvotes": new_reactions["upvotes"],
|
||||
"new_reaction_counts": new_reactions["counts"],
|
||||
"body_excerpt": compact_text(comment.get("body"), comment_chars),
|
||||
}
|
||||
|
||||
|
||||
def summarize_issue(
|
||||
issue,
|
||||
comments,
|
||||
requested_labels,
|
||||
since,
|
||||
until,
|
||||
body_chars,
|
||||
comment_chars,
|
||||
issue_reaction_events=None,
|
||||
comment_reactions_by_id=None,
|
||||
all_labels=False,
|
||||
comments_hydration=None,
|
||||
attention_thresholds=None,
|
||||
):
|
||||
labels = label_names(issue)
|
||||
labels_by_key = {label.casefold() for label in labels}
|
||||
kind_labels = [
|
||||
label for label in QUALIFYING_KIND_LABELS if label.casefold() in labels_by_key
|
||||
]
|
||||
if all_labels:
|
||||
owner_labels = area_labels(labels) or ["unlabeled"]
|
||||
else:
|
||||
owner_labels = matching_labels(labels, requested_labels)
|
||||
if not kind_labels or not owner_labels:
|
||||
return None
|
||||
|
||||
updated_at = str(issue.get("updated_at") or "")
|
||||
if not is_in_window(updated_at, since, until):
|
||||
return None
|
||||
|
||||
new_issue = is_in_window(str(issue.get("created_at") or ""), since, until)
|
||||
comment_reactions_by_id = comment_reactions_by_id or {}
|
||||
new_comments = [
|
||||
summarize_comment(
|
||||
comment,
|
||||
comment_chars,
|
||||
reaction_events=comment_reactions_by_id.get(comment.get("id")),
|
||||
since=since,
|
||||
until=until,
|
||||
)
|
||||
for comment in comments
|
||||
if is_in_window(str(comment.get("created_at") or ""), since, until)
|
||||
]
|
||||
new_comments.sort(key=lambda item: (item["created_at"], str(item["id"])))
|
||||
|
||||
issue_reactions = reaction_summary(issue)
|
||||
issue_reaction_events_summary = reaction_event_summary(
|
||||
issue_reaction_events, since, until
|
||||
)
|
||||
comment_reaction_events_summary = reaction_event_summary(
|
||||
[
|
||||
reaction
|
||||
for reactions in comment_reactions_by_id.values()
|
||||
for reaction in reactions
|
||||
],
|
||||
since,
|
||||
until,
|
||||
)
|
||||
new_reactions = (
|
||||
issue_reaction_events_summary["total"]
|
||||
+ comment_reaction_events_summary["total"]
|
||||
)
|
||||
new_upvotes = (
|
||||
issue_reaction_events_summary["upvotes"]
|
||||
+ comment_reaction_events_summary["upvotes"]
|
||||
)
|
||||
all_comment_reaction_total = sum(
|
||||
reaction_summary(comment)["total"] for comment in comments
|
||||
)
|
||||
new_comment_reaction_total = sum(
|
||||
comment["reaction_total"] for comment in new_comments
|
||||
)
|
||||
new_issue_user_interaction = new_issue and is_human_user(issue.get("user"))
|
||||
new_comment_user_interactions = sum(
|
||||
1 for comment in new_comments if comment["human_user_interaction"]
|
||||
)
|
||||
user_interactions = (
|
||||
int(new_issue_user_interaction) + new_comment_user_interactions + new_reactions
|
||||
)
|
||||
attention_level = attention_level_for(user_interactions, attention_thresholds)
|
||||
attention_marker = attention_marker_for(user_interactions, attention_thresholds)
|
||||
updated_without_visible_new_post = (
|
||||
not new_issue and not new_comments and new_reactions == 0
|
||||
)
|
||||
|
||||
engagement_score = (
|
||||
len(new_comments) * 3
|
||||
+ new_reactions
|
||||
+ issue_reactions["total"]
|
||||
+ new_comment_reaction_total
|
||||
+ min(int(issue.get("comments") or len(comments) or 0), 10)
|
||||
)
|
||||
|
||||
return {
|
||||
"number": issue.get("number"),
|
||||
"title": str(issue.get("title") or ""),
|
||||
"description": issue_description(issue),
|
||||
"url": str(issue.get("html_url") or ""),
|
||||
"state": str(issue.get("state") or ""),
|
||||
"author": extract_login(issue.get("user")),
|
||||
"author_association": str(issue.get("author_association") or ""),
|
||||
"created_at": str(issue.get("created_at") or ""),
|
||||
"updated_at": updated_at,
|
||||
"labels": labels,
|
||||
"kind_labels": kind_labels,
|
||||
"owner_labels": owner_labels,
|
||||
"comments_total": int(issue.get("comments") or len(comments) or 0),
|
||||
"comments_hydration": comments_hydration
|
||||
or {
|
||||
"fetched": len(comments),
|
||||
"since": None,
|
||||
"truncated": False,
|
||||
"max_pages": None,
|
||||
},
|
||||
"issue_reactions": issue_reactions["counts"],
|
||||
"issue_reaction_total": issue_reactions["total"],
|
||||
"comment_reaction_total": all_comment_reaction_total,
|
||||
"new_comment_reaction_total": new_comment_reaction_total,
|
||||
"new_issue_reactions": issue_reaction_events_summary["total"],
|
||||
"new_issue_upvotes": issue_reaction_events_summary["upvotes"],
|
||||
"new_comment_reactions": comment_reaction_events_summary["total"],
|
||||
"new_comment_upvotes": comment_reaction_events_summary["upvotes"],
|
||||
"new_reactions": new_reactions,
|
||||
"new_upvotes": new_upvotes,
|
||||
"user_interactions": user_interactions,
|
||||
"attention": attention_level > 0,
|
||||
"attention_level": attention_level,
|
||||
"attention_marker": attention_marker,
|
||||
"engagement_score": engagement_score,
|
||||
"activity": {
|
||||
"new_issue": new_issue,
|
||||
"new_comments": len(new_comments),
|
||||
"new_human_comments": new_comment_user_interactions,
|
||||
"new_reactions": new_reactions,
|
||||
"new_upvotes": new_upvotes,
|
||||
"updated_without_visible_new_post": updated_without_visible_new_post,
|
||||
},
|
||||
"body_excerpt": compact_text(issue.get("body"), body_chars),
|
||||
"new_comments": new_comments,
|
||||
}
|
||||
|
||||
|
||||
def count_by_label(issues, labels):
|
||||
out = {}
|
||||
for label in labels:
|
||||
matching = [issue for issue in issues if label in issue["owner_labels"]]
|
||||
out[label] = {
|
||||
"issues": len(matching),
|
||||
"new_issues": sum(
|
||||
1 for issue in matching if issue["activity"]["new_issue"]
|
||||
),
|
||||
"new_comments": sum(
|
||||
issue["activity"]["new_comments"] for issue in matching
|
||||
),
|
||||
}
|
||||
return out
|
||||
|
||||
|
||||
def count_by_kind(issues):
|
||||
out = {}
|
||||
for kind in QUALIFYING_KIND_LABELS:
|
||||
matching = [issue for issue in issues if kind in issue["kind_labels"]]
|
||||
out[kind] = {
|
||||
"issues": len(matching),
|
||||
"new_issues": sum(
|
||||
1 for issue in matching if issue["activity"]["new_issue"]
|
||||
),
|
||||
"new_comments": sum(
|
||||
issue["activity"]["new_comments"] for issue in matching
|
||||
),
|
||||
}
|
||||
return out
|
||||
|
||||
|
||||
def hot_items(issues, limit=8):
|
||||
ranked = sorted(
|
||||
issues,
|
||||
key=lambda issue: (
|
||||
issue["attention"],
|
||||
issue["attention_level"],
|
||||
issue["user_interactions"],
|
||||
issue["engagement_score"],
|
||||
issue["activity"]["new_comments"],
|
||||
issue["issue_reaction_total"] + issue["comment_reaction_total"],
|
||||
issue["updated_at"],
|
||||
),
|
||||
reverse=True,
|
||||
)
|
||||
return [
|
||||
{
|
||||
"number": issue["number"],
|
||||
"title": issue["title"],
|
||||
"url": issue["url"],
|
||||
"owner_labels": issue["owner_labels"],
|
||||
"kind_labels": issue["kind_labels"],
|
||||
"attention": issue["attention"],
|
||||
"attention_level": issue["attention_level"],
|
||||
"attention_marker": issue["attention_marker"],
|
||||
"user_interactions": issue["user_interactions"],
|
||||
"new_reactions": issue["new_reactions"],
|
||||
"new_upvotes": issue["new_upvotes"],
|
||||
"engagement_score": issue["engagement_score"],
|
||||
"new_comments": issue["activity"]["new_comments"],
|
||||
"reaction_total": issue["issue_reaction_total"]
|
||||
+ issue["comment_reaction_total"],
|
||||
}
|
||||
for issue in ranked[:limit]
|
||||
if issue["engagement_score"] > 0
|
||||
]
|
||||
|
||||
|
||||
def ranked_digest_issues(issues):
|
||||
return sorted(
|
||||
issues,
|
||||
key=lambda issue: (
|
||||
issue["attention"],
|
||||
issue["attention_level"],
|
||||
issue["user_interactions"],
|
||||
issue["engagement_score"],
|
||||
issue["activity"]["new_comments"],
|
||||
issue["updated_at"],
|
||||
),
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
|
||||
def digest_rows(issues, limit=10, ref_map=None):
|
||||
ranked = ranked_digest_issues(issues)
|
||||
if ref_map is None:
|
||||
ref_map = {issue["number"]: ref for ref, issue in enumerate(ranked, start=1)}
|
||||
rows = []
|
||||
for issue in ranked[:limit]:
|
||||
ref = ref_map[issue["number"]]
|
||||
reaction_total = issue["issue_reaction_total"] + issue["comment_reaction_total"]
|
||||
rows.append(
|
||||
{
|
||||
"ref": ref,
|
||||
"ref_markdown": f"[{ref}]({issue['url']})",
|
||||
"marker": issue["attention_marker"],
|
||||
"attention_marker": issue["attention_marker"],
|
||||
"number": issue["number"],
|
||||
"description": issue["description"],
|
||||
"title": issue["title"],
|
||||
"url": issue["url"],
|
||||
"area": ", ".join(issue["owner_labels"]),
|
||||
"kind": ", ".join(issue["kind_labels"]),
|
||||
"state": issue["state"],
|
||||
"interactions": issue["user_interactions"],
|
||||
"user_interactions": issue["user_interactions"],
|
||||
"new_reactions": issue["new_reactions"],
|
||||
"new_upvotes": issue["new_upvotes"],
|
||||
"current_reactions": reaction_total,
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def issue_ref_markdown(issue, ref_map):
|
||||
ref = ref_map[issue["number"]]
|
||||
return f"[{ref}]({issue['url']})"
|
||||
|
||||
|
||||
def summary_inputs(issues, limit=80, ref_map=None):
|
||||
ranked = ranked_digest_issues(issues)
|
||||
if ref_map is None:
|
||||
ref_map = {issue["number"]: ref for ref, issue in enumerate(ranked, start=1)}
|
||||
rows = []
|
||||
for issue in ranked[:limit]:
|
||||
rows.append(
|
||||
{
|
||||
"ref": ref_map[issue["number"]],
|
||||
"ref_markdown": issue_ref_markdown(issue, ref_map),
|
||||
"number": issue["number"],
|
||||
"title": issue["title"],
|
||||
"description": issue["description"],
|
||||
"url": issue["url"],
|
||||
"labels": issue["labels"],
|
||||
"owner_labels": issue["owner_labels"],
|
||||
"kind_labels": issue["kind_labels"],
|
||||
"state": issue.get("state", ""),
|
||||
"attention_marker": issue.get("attention_marker", ""),
|
||||
"interactions": issue["user_interactions"],
|
||||
"new_comments": issue["activity"].get("new_comments", 0),
|
||||
"new_reactions": issue.get("new_reactions", 0),
|
||||
"new_upvotes": issue.get("new_upvotes", 0),
|
||||
"current_reactions": issue.get("issue_reaction_total", 0)
|
||||
+ issue.get("comment_reaction_total", 0),
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def collect_digest(args):
|
||||
since, until = resolve_window(args)
|
||||
window_hours = (until - since).total_seconds() / 3600
|
||||
attention_thresholds = attention_thresholds_for_window(window_hours)
|
||||
requested_labels, all_labels = normalize_requested_labels(
|
||||
args.labels, all_labels=args.all_labels
|
||||
)
|
||||
queries = build_search_queries(
|
||||
args.repo, requested_labels, since, all_labels=all_labels
|
||||
)
|
||||
numbers = search_issue_numbers(queries, args.limit_issues)
|
||||
gh_version_output = gh_text(["--version"])
|
||||
|
||||
issues = []
|
||||
max_comment_pages = None if args.max_comment_pages <= 0 else args.max_comment_pages
|
||||
for number in numbers:
|
||||
issue = fetch_issue(args.repo, number)
|
||||
comments_since = None if args.fetch_all_comments else since
|
||||
comments_payload = fetch_comments(
|
||||
args.repo,
|
||||
number,
|
||||
since=comments_since,
|
||||
max_pages=max_comment_pages,
|
||||
)
|
||||
comments = comments_payload["items"]
|
||||
issue_reaction_events = fetch_reactions_for_item(
|
||||
f"repos/{args.repo}/issues/{number}/reactions", issue
|
||||
)
|
||||
comment_reactions_by_id = fetch_comment_reactions(args.repo, comments)
|
||||
comments_hydration = {
|
||||
"fetched": len(comments),
|
||||
"total": int(issue.get("comments") or len(comments) or 0),
|
||||
"since": format_timestamp(comments_since) if comments_since else None,
|
||||
"truncated": comments_payload["truncated"],
|
||||
"max_pages": comments_payload["max_pages"],
|
||||
"fetch_all_comments": args.fetch_all_comments,
|
||||
}
|
||||
summary = summarize_issue(
|
||||
issue,
|
||||
comments,
|
||||
requested_labels,
|
||||
since,
|
||||
until,
|
||||
args.body_chars,
|
||||
args.comment_chars,
|
||||
issue_reaction_events=issue_reaction_events,
|
||||
comment_reactions_by_id=comment_reactions_by_id,
|
||||
all_labels=all_labels,
|
||||
comments_hydration=comments_hydration,
|
||||
attention_thresholds=attention_thresholds,
|
||||
)
|
||||
if summary is not None:
|
||||
issues.append(summary)
|
||||
|
||||
issues.sort(
|
||||
key=lambda issue: (issue["updated_at"], int(issue["number"] or 0)), reverse=True
|
||||
)
|
||||
totals = {
|
||||
"candidate_issues": len(numbers),
|
||||
"included_issues": len(issues),
|
||||
"new_issues": sum(1 for issue in issues if issue["activity"]["new_issue"]),
|
||||
"issues_with_new_comments": sum(
|
||||
1 for issue in issues if issue["activity"]["new_comments"] > 0
|
||||
),
|
||||
"new_comments": sum(issue["activity"]["new_comments"] for issue in issues),
|
||||
"comments_fetched": sum(
|
||||
issue["comments_hydration"]["fetched"] for issue in issues
|
||||
),
|
||||
"issues_with_truncated_comment_hydration": sum(
|
||||
1 for issue in issues if issue["comments_hydration"]["truncated"]
|
||||
),
|
||||
"updated_without_visible_new_post": sum(
|
||||
1
|
||||
for issue in issues
|
||||
if issue["activity"]["updated_without_visible_new_post"]
|
||||
),
|
||||
"issue_reactions_current_total": sum(
|
||||
issue["issue_reaction_total"] for issue in issues
|
||||
),
|
||||
"comment_reactions_current_total": sum(
|
||||
issue["comment_reaction_total"] for issue in issues
|
||||
),
|
||||
"new_reactions": sum(issue["new_reactions"] for issue in issues),
|
||||
"new_upvotes": sum(issue["new_upvotes"] for issue in issues),
|
||||
"user_interactions": sum(issue["user_interactions"] for issue in issues),
|
||||
}
|
||||
ranked = ranked_digest_issues(issues)
|
||||
ref_map = {issue["number"]: ref for ref, issue in enumerate(ranked, start=1)}
|
||||
filter_label = "all" if all_labels else requested_labels
|
||||
|
||||
return {
|
||||
"generated_at": format_timestamp(datetime.now(timezone.utc)),
|
||||
"source": {
|
||||
"repo": args.repo,
|
||||
"skill": "codex-issue-digest",
|
||||
"collector": skill_relative_path(),
|
||||
"script_version": SCRIPT_VERSION,
|
||||
"git_head": git_head(),
|
||||
"gh_version": gh_version_output.splitlines()[0]
|
||||
if gh_version_output
|
||||
else None,
|
||||
},
|
||||
"window": {
|
||||
"since": format_timestamp(since),
|
||||
"until": format_timestamp(until),
|
||||
"hours": round(window_hours, 3),
|
||||
},
|
||||
"attention_thresholds": attention_thresholds,
|
||||
"filters": {
|
||||
"owner_labels": filter_label,
|
||||
"all_labels": all_labels,
|
||||
"kind_labels": list(QUALIFYING_KIND_LABELS),
|
||||
},
|
||||
"collection_notes": [
|
||||
"Issues are selected when they currently have bug or enhancement plus at least one requested owner label and were updated during the window.",
|
||||
"By default, issue comments are fetched with since=window_start and a max page cap to avoid long historical threads; use --fetch-all-comments when exhaustive comment history is needed.",
|
||||
"New issue comments are filtered by comment creation time within the window from the fetched comment set.",
|
||||
"Reaction events are counted by GitHub reaction created_at timestamps for hydrated issues and fetched comments.",
|
||||
"Current reaction totals are standing engagement signals; new_reactions and new_upvotes are windowed activity.",
|
||||
"The collector does not assign semantic clusters; use summary_inputs as model-ready evidence for report-time clustering.",
|
||||
"Pure reaction-only issues may be missed if GitHub issue search does not surface them via updated_at.",
|
||||
"Issues updated during the window without a new issue body or new comment are retained because label/status edits can still be useful owner signals.",
|
||||
],
|
||||
"totals": totals,
|
||||
"by_owner_label": count_by_label(
|
||||
issues,
|
||||
sorted(
|
||||
{area for issue in issues for area in issue["owner_labels"]},
|
||||
key=str.casefold,
|
||||
)
|
||||
if all_labels
|
||||
else requested_labels,
|
||||
),
|
||||
"by_kind_label": count_by_kind(issues),
|
||||
"hot_items": hot_items(issues),
|
||||
"summary_inputs": summary_inputs(issues, ref_map=ref_map),
|
||||
"digest_rows": digest_rows(issues, ref_map=ref_map),
|
||||
"issues": issues,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
try:
|
||||
digest = collect_digest(args)
|
||||
except (GhCommandError, RuntimeError, ValueError) as err:
|
||||
sys.stderr.write(f"collect_issue_digest.py error: {err}\n")
|
||||
return 1
|
||||
sys.stdout.write(json.dumps(digest, indent=2, sort_keys=True) + "\n")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,614 @@
|
||||
import importlib.util
|
||||
from datetime import timezone
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
MODULE_PATH = Path(__file__).with_name("collect_issue_digest.py")
|
||||
MODULE_SPEC = importlib.util.spec_from_file_location(
|
||||
"collect_issue_digest", MODULE_PATH
|
||||
)
|
||||
collect_issue_digest = importlib.util.module_from_spec(MODULE_SPEC)
|
||||
assert MODULE_SPEC.loader is not None
|
||||
MODULE_SPEC.loader.exec_module(collect_issue_digest)
|
||||
|
||||
|
||||
def test_build_search_queries_uses_each_owner_and_kind_label():
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T12:34:56Z", "--since")
|
||||
|
||||
queries = collect_issue_digest.build_search_queries(
|
||||
"openai/codex", ["tui", "exec"], since
|
||||
)
|
||||
|
||||
assert queries == [
|
||||
"repo:openai/codex is:issue updated:>=2026-04-25 label:tui label:bug",
|
||||
"repo:openai/codex is:issue updated:>=2026-04-25 label:tui label:enhancement",
|
||||
"repo:openai/codex is:issue updated:>=2026-04-25 label:exec label:bug",
|
||||
"repo:openai/codex is:issue updated:>=2026-04-25 label:exec label:enhancement",
|
||||
]
|
||||
|
||||
|
||||
def test_build_search_queries_can_scan_all_labels():
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T12:34:56Z", "--since")
|
||||
|
||||
queries = collect_issue_digest.build_search_queries(
|
||||
"openai/codex", [], since, all_labels=True
|
||||
)
|
||||
|
||||
assert queries == [
|
||||
"repo:openai/codex is:issue updated:>=2026-04-25 label:bug",
|
||||
"repo:openai/codex is:issue updated:>=2026-04-25 label:enhancement",
|
||||
]
|
||||
|
||||
|
||||
def test_normalize_requested_labels_accepts_all_area_phrases():
|
||||
assert collect_issue_digest.normalize_requested_labels(["all", "areas"]) == (
|
||||
[],
|
||||
True,
|
||||
)
|
||||
assert collect_issue_digest.normalize_requested_labels(["all-labels"]) == (
|
||||
[],
|
||||
True,
|
||||
)
|
||||
|
||||
|
||||
def test_summarize_issue_keeps_new_comments_and_reaction_signals():
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T00:00:00Z", "--since")
|
||||
until = collect_issue_digest.parse_timestamp("2026-04-26T00:00:00Z", "--until")
|
||||
issue = {
|
||||
"number": 123,
|
||||
"title": "TUI does not redraw",
|
||||
"html_url": "https://github.com/openai/codex/issues/123",
|
||||
"state": "open",
|
||||
"created_at": "2026-04-24T20:00:00Z",
|
||||
"updated_at": "2026-04-25T10:00:00Z",
|
||||
"user": {"login": "alice"},
|
||||
"author_association": "NONE",
|
||||
"comments": 2,
|
||||
"body": "The terminal freezes after resize.",
|
||||
"labels": [{"name": "bug"}, {"name": "tui"}],
|
||||
"reactions": {"total_count": 3, "+1": 2, "rocket": 1},
|
||||
}
|
||||
comments = [
|
||||
{
|
||||
"id": 1,
|
||||
"created_at": "2026-04-25T11:00:00Z",
|
||||
"updated_at": "2026-04-25T11:00:00Z",
|
||||
"html_url": "https://github.com/openai/codex/issues/123#issuecomment-1",
|
||||
"user": {"login": "bob"},
|
||||
"author_association": "MEMBER",
|
||||
"body": "I can reproduce this on main.",
|
||||
"reactions": {"total_count": 4, "heart": 1, "+1": 3},
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"created_at": "2026-04-24T11:00:00Z",
|
||||
"updated_at": "2026-04-24T11:00:00Z",
|
||||
"html_url": "https://github.com/openai/codex/issues/123#issuecomment-2",
|
||||
"user": {"login": "carol"},
|
||||
"author_association": "NONE",
|
||||
"body": "Older comment.",
|
||||
"reactions": {"total_count": 1, "eyes": 1},
|
||||
},
|
||||
]
|
||||
|
||||
summary = collect_issue_digest.summarize_issue(
|
||||
issue,
|
||||
comments,
|
||||
["tui", "exec"],
|
||||
since,
|
||||
until,
|
||||
body_chars=200,
|
||||
comment_chars=200,
|
||||
)
|
||||
|
||||
assert summary == {
|
||||
"number": 123,
|
||||
"title": "TUI does not redraw",
|
||||
"description": "TUI does not redraw",
|
||||
"url": "https://github.com/openai/codex/issues/123",
|
||||
"state": "open",
|
||||
"author": "alice",
|
||||
"author_association": "NONE",
|
||||
"created_at": "2026-04-24T20:00:00Z",
|
||||
"updated_at": "2026-04-25T10:00:00Z",
|
||||
"labels": ["bug", "tui"],
|
||||
"kind_labels": ["bug"],
|
||||
"owner_labels": ["tui"],
|
||||
"comments_total": 2,
|
||||
"comments_hydration": {
|
||||
"fetched": 2,
|
||||
"since": None,
|
||||
"truncated": False,
|
||||
"max_pages": None,
|
||||
},
|
||||
"issue_reactions": {"+1": 2, "rocket": 1},
|
||||
"issue_reaction_total": 3,
|
||||
"comment_reaction_total": 5,
|
||||
"new_comment_reaction_total": 4,
|
||||
"new_issue_reactions": 0,
|
||||
"new_issue_upvotes": 0,
|
||||
"new_comment_reactions": 0,
|
||||
"new_comment_upvotes": 0,
|
||||
"new_reactions": 0,
|
||||
"new_upvotes": 0,
|
||||
"user_interactions": 1,
|
||||
"attention": False,
|
||||
"attention_level": 0,
|
||||
"attention_marker": "",
|
||||
"engagement_score": 12,
|
||||
"activity": {
|
||||
"new_issue": False,
|
||||
"new_comments": 1,
|
||||
"new_human_comments": 1,
|
||||
"new_reactions": 0,
|
||||
"new_upvotes": 0,
|
||||
"updated_without_visible_new_post": False,
|
||||
},
|
||||
"body_excerpt": "The terminal freezes after resize.",
|
||||
"new_comments": [
|
||||
{
|
||||
"id": 1,
|
||||
"author": "bob",
|
||||
"author_association": "MEMBER",
|
||||
"created_at": "2026-04-25T11:00:00Z",
|
||||
"updated_at": "2026-04-25T11:00:00Z",
|
||||
"url": "https://github.com/openai/codex/issues/123#issuecomment-1",
|
||||
"human_user_interaction": True,
|
||||
"reactions": {"+1": 3, "heart": 1},
|
||||
"reaction_total": 4,
|
||||
"new_reactions": 0,
|
||||
"new_upvotes": 0,
|
||||
"new_reaction_counts": {},
|
||||
"body_excerpt": "I can reproduce this on main.",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_summarize_issue_filters_non_owner_or_non_kind_labels():
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T00:00:00Z", "--since")
|
||||
until = collect_issue_digest.parse_timestamp("2026-04-26T00:00:00Z", "--until")
|
||||
base_issue = {
|
||||
"number": 1,
|
||||
"title": "Question",
|
||||
"created_at": "2026-04-25T01:00:00Z",
|
||||
"updated_at": "2026-04-25T01:00:00Z",
|
||||
"labels": [{"name": "question"}, {"name": "tui"}],
|
||||
}
|
||||
|
||||
assert (
|
||||
collect_issue_digest.summarize_issue(
|
||||
base_issue,
|
||||
[],
|
||||
["tui"],
|
||||
since,
|
||||
until,
|
||||
body_chars=100,
|
||||
comment_chars=100,
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
issue_without_owner = dict(base_issue)
|
||||
issue_without_owner["labels"] = [{"name": "bug"}, {"name": "app"}]
|
||||
|
||||
assert (
|
||||
collect_issue_digest.summarize_issue(
|
||||
issue_without_owner,
|
||||
[],
|
||||
["tui"],
|
||||
since,
|
||||
until,
|
||||
body_chars=100,
|
||||
comment_chars=100,
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
|
||||
def test_resolve_window_defaults_to_previous_hours():
|
||||
class Args:
|
||||
since = None
|
||||
until = "2026-04-26T12:00:00Z"
|
||||
window_hours = 24
|
||||
|
||||
since, until = collect_issue_digest.resolve_window(Args())
|
||||
|
||||
assert since.isoformat() == "2026-04-25T12:00:00+00:00"
|
||||
assert until.tzinfo == timezone.utc
|
||||
|
||||
|
||||
def test_parse_duration_hours_accepts_common_phrases():
|
||||
assert collect_issue_digest.parse_duration_hours("past week") == 168
|
||||
assert collect_issue_digest.parse_duration_hours("48h") == 48
|
||||
assert collect_issue_digest.parse_duration_hours("2 days") == 48
|
||||
assert collect_issue_digest.parse_duration_hours("1w") == 168
|
||||
|
||||
|
||||
def test_attention_thresholds_scale_by_window_length():
|
||||
one_day = collect_issue_digest.attention_thresholds_for_window(24)
|
||||
assert one_day["elevated"] == 10
|
||||
assert one_day["very_high"] == 20
|
||||
|
||||
half_day = collect_issue_digest.attention_thresholds_for_window(12)
|
||||
assert half_day["elevated"] == 5
|
||||
assert half_day["very_high"] == 10
|
||||
|
||||
week = collect_issue_digest.attention_thresholds_for_window(168)
|
||||
assert week["elevated"] == 70
|
||||
assert week["very_high"] == 140
|
||||
assert collect_issue_digest.attention_marker_for(69, week) == ""
|
||||
assert collect_issue_digest.attention_marker_for(107, week) == "🔥"
|
||||
assert collect_issue_digest.attention_marker_for(140, week) == "🔥🔥"
|
||||
|
||||
|
||||
def test_fetch_comments_uses_since_filter_and_page_cap(monkeypatch):
|
||||
calls = []
|
||||
|
||||
def fake_gh_json(args):
|
||||
calls.append(args)
|
||||
return [{"id": idx} for idx in range(100)]
|
||||
|
||||
monkeypatch.setattr(collect_issue_digest, "gh_json", fake_gh_json)
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T00:00:00Z", "--since")
|
||||
|
||||
payload = collect_issue_digest.fetch_comments(
|
||||
"openai/codex", 123, since=since, max_pages=1
|
||||
)
|
||||
|
||||
assert len(payload["items"]) == 100
|
||||
assert payload["truncated"] is True
|
||||
assert payload["max_pages"] == 1
|
||||
assert calls == [
|
||||
[
|
||||
"api",
|
||||
"repos/openai/codex/issues/123/comments?since=2026-04-25T00%3A00%3A00Z&per_page=100&page=1",
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
def test_issue_description_prefers_title_over_body_noise():
|
||||
issue = {
|
||||
"title": "Codex.app GUI: MCP child processes not reaped after task completion",
|
||||
"body": "A later crash mention should not override the title-level symptom.",
|
||||
"labels": [{"name": "app"}, {"name": "bug"}],
|
||||
}
|
||||
|
||||
description = collect_issue_digest.issue_description(issue)
|
||||
assert "MCP child processes" in description
|
||||
assert "crash" not in description.casefold()
|
||||
|
||||
|
||||
def test_attention_markers_count_human_user_interactions():
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T00:00:00Z", "--since")
|
||||
until = collect_issue_digest.parse_timestamp("2026-04-26T00:00:00Z", "--until")
|
||||
issue = {
|
||||
"number": 456,
|
||||
"title": "Agent context is exploding",
|
||||
"html_url": "https://github.com/openai/codex/issues/456",
|
||||
"state": "open",
|
||||
"created_at": "2026-04-25T01:00:00Z",
|
||||
"updated_at": "2026-04-25T12:00:00Z",
|
||||
"user": {"login": "alice"},
|
||||
"labels": [{"name": "bug"}, {"name": "agent"}],
|
||||
}
|
||||
comments = [
|
||||
{
|
||||
"id": idx,
|
||||
"created_at": "2026-04-25T02:00:00Z",
|
||||
"updated_at": "2026-04-25T02:00:00Z",
|
||||
"user": {"login": f"user-{idx}"},
|
||||
"body": "same here",
|
||||
}
|
||||
for idx in range(9)
|
||||
]
|
||||
comments.append(
|
||||
{
|
||||
"id": 99,
|
||||
"created_at": "2026-04-25T02:00:00Z",
|
||||
"updated_at": "2026-04-25T02:00:00Z",
|
||||
"user": {"login": "github-actions[bot]"},
|
||||
"body": "duplicate bot note",
|
||||
}
|
||||
)
|
||||
|
||||
summary = collect_issue_digest.summarize_issue(
|
||||
issue,
|
||||
comments,
|
||||
["agent"],
|
||||
since,
|
||||
until,
|
||||
body_chars=100,
|
||||
comment_chars=100,
|
||||
)
|
||||
|
||||
assert summary["user_interactions"] == 10
|
||||
assert summary["activity"]["new_human_comments"] == 9
|
||||
assert summary["attention"] is True
|
||||
assert summary["attention_level"] == 1
|
||||
assert summary["attention_marker"] == "🔥"
|
||||
|
||||
issue["created_at"] = "2026-04-24T01:00:00Z"
|
||||
comments.extend(
|
||||
{
|
||||
"id": idx,
|
||||
"created_at": "2026-04-25T03:00:00Z",
|
||||
"updated_at": "2026-04-25T03:00:00Z",
|
||||
"user": {"login": f"extra-user-{idx}"},
|
||||
"body": "also seeing this",
|
||||
}
|
||||
for idx in range(11)
|
||||
)
|
||||
|
||||
summary = collect_issue_digest.summarize_issue(
|
||||
issue,
|
||||
comments,
|
||||
["agent"],
|
||||
since,
|
||||
until,
|
||||
body_chars=100,
|
||||
comment_chars=100,
|
||||
)
|
||||
|
||||
assert summary["user_interactions"] == 20
|
||||
assert summary["attention_level"] == 2
|
||||
assert summary["attention_marker"] == "🔥🔥"
|
||||
|
||||
|
||||
def test_reactions_count_toward_attention_markers():
|
||||
since = collect_issue_digest.parse_timestamp("2026-04-25T00:00:00Z", "--since")
|
||||
until = collect_issue_digest.parse_timestamp("2026-04-26T00:00:00Z", "--until")
|
||||
issue = {
|
||||
"number": 789,
|
||||
"title": "Support 1M token context",
|
||||
"html_url": "https://github.com/openai/codex/issues/789",
|
||||
"state": "open",
|
||||
"created_at": "2026-04-24T01:00:00Z",
|
||||
"updated_at": "2026-04-25T12:00:00Z",
|
||||
"user": {"login": "alice"},
|
||||
"labels": [{"name": "enhancement"}, {"name": "context"}],
|
||||
"reactions": {"total_count": 20, "+1": 20},
|
||||
}
|
||||
comments = [
|
||||
{
|
||||
"id": 1,
|
||||
"created_at": "2026-04-25T02:00:00Z",
|
||||
"updated_at": "2026-04-25T02:00:00Z",
|
||||
"user": {"login": "commenter"},
|
||||
"body": "please",
|
||||
"reactions": {"total_count": 2, "+1": 2},
|
||||
}
|
||||
]
|
||||
issue_reactions = [
|
||||
{
|
||||
"content": "+1",
|
||||
"created_at": "2026-04-25T03:00:00Z",
|
||||
"user": {"login": f"reactor-{idx}"},
|
||||
}
|
||||
for idx in range(18)
|
||||
]
|
||||
comment_reactions_by_id = {
|
||||
1: [
|
||||
{
|
||||
"content": "heart",
|
||||
"created_at": "2026-04-25T04:00:00Z",
|
||||
"user": {"login": "human-reactor"},
|
||||
},
|
||||
{
|
||||
"content": "+1",
|
||||
"created_at": "2026-04-25T04:00:00Z",
|
||||
"user": {"login": "github-actions[bot]"},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
summary = collect_issue_digest.summarize_issue(
|
||||
issue,
|
||||
comments,
|
||||
["context"],
|
||||
since,
|
||||
until,
|
||||
body_chars=100,
|
||||
comment_chars=100,
|
||||
issue_reaction_events=issue_reactions,
|
||||
comment_reactions_by_id=comment_reactions_by_id,
|
||||
)
|
||||
|
||||
assert summary["new_reactions"] == 19
|
||||
assert summary["new_upvotes"] == 18
|
||||
assert summary["user_interactions"] == 20
|
||||
assert summary["attention_level"] == 2
|
||||
assert summary["attention_marker"] == "🔥🔥"
|
||||
assert summary["new_comments"][0]["new_reactions"] == 1
|
||||
assert summary["new_comments"][0]["new_upvotes"] == 0
|
||||
|
||||
|
||||
def test_digest_rows_are_table_ready_with_concise_descriptions():
|
||||
rows = collect_issue_digest.digest_rows(
|
||||
[
|
||||
{
|
||||
"number": 1,
|
||||
"title": "Quiet bug",
|
||||
"description": "Quiet bug",
|
||||
"url": "https://github.com/openai/codex/issues/1",
|
||||
"owner_labels": ["context"],
|
||||
"kind_labels": ["bug"],
|
||||
"state": "open",
|
||||
"attention": False,
|
||||
"attention_level": 0,
|
||||
"attention_marker": "",
|
||||
"user_interactions": 1,
|
||||
"new_reactions": 0,
|
||||
"new_upvotes": 0,
|
||||
"engagement_score": 3,
|
||||
"issue_reaction_total": 0,
|
||||
"comment_reaction_total": 0,
|
||||
"updated_at": "2026-04-25T01:00:00Z",
|
||||
"activity": {
|
||||
"new_issue": True,
|
||||
"new_comments": 0,
|
||||
"new_reactions": 0,
|
||||
"updated_without_visible_new_post": False,
|
||||
},
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"title": "Busy bug",
|
||||
"description": "High-volume bug report",
|
||||
"url": "https://github.com/openai/codex/issues/2",
|
||||
"owner_labels": ["agent"],
|
||||
"kind_labels": ["bug"],
|
||||
"state": "open",
|
||||
"attention": True,
|
||||
"attention_level": 1,
|
||||
"attention_marker": "🔥",
|
||||
"user_interactions": 17,
|
||||
"new_reactions": 3,
|
||||
"new_upvotes": 2,
|
||||
"engagement_score": 20,
|
||||
"issue_reaction_total": 5,
|
||||
"comment_reaction_total": 2,
|
||||
"updated_at": "2026-04-25T02:00:00Z",
|
||||
"activity": {
|
||||
"new_issue": False,
|
||||
"new_comments": 16,
|
||||
"new_reactions": 3,
|
||||
"updated_without_visible_new_post": False,
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
assert rows[0] == {
|
||||
"ref": 1,
|
||||
"ref_markdown": "[1](https://github.com/openai/codex/issues/2)",
|
||||
"marker": "🔥",
|
||||
"attention_marker": "🔥",
|
||||
"number": 2,
|
||||
"description": "High-volume bug report",
|
||||
"title": "Busy bug",
|
||||
"url": "https://github.com/openai/codex/issues/2",
|
||||
"area": "agent",
|
||||
"kind": "bug",
|
||||
"state": "open",
|
||||
"interactions": 17,
|
||||
"user_interactions": 17,
|
||||
"new_reactions": 3,
|
||||
"new_upvotes": 2,
|
||||
"current_reactions": 7,
|
||||
}
|
||||
|
||||
|
||||
def test_summary_inputs_are_model_ready_without_preclustering():
|
||||
issues = [
|
||||
{
|
||||
"number": 20,
|
||||
"title": "Windows app Browser Use external navigation fails",
|
||||
"description": "Browser Use navigation or app-server failure",
|
||||
"url": "https://github.com/openai/codex/issues/20",
|
||||
"labels": ["app", "bug"],
|
||||
"owner_labels": ["app"],
|
||||
"kind_labels": ["bug"],
|
||||
"attention": False,
|
||||
"attention_level": 0,
|
||||
"attention_marker": "",
|
||||
"user_interactions": 3,
|
||||
"new_reactions": 1,
|
||||
"engagement_score": 8,
|
||||
"updated_at": "2026-04-25T04:00:00Z",
|
||||
"activity": {"new_comments": 2},
|
||||
},
|
||||
{
|
||||
"number": 21,
|
||||
"title": "On Windows, cmake output waits until timeout",
|
||||
"description": "Windows command timeout/capture problem",
|
||||
"url": "https://github.com/openai/codex/issues/21",
|
||||
"labels": ["app", "bug"],
|
||||
"owner_labels": ["app"],
|
||||
"kind_labels": ["bug"],
|
||||
"attention": False,
|
||||
"attention_level": 0,
|
||||
"attention_marker": "",
|
||||
"user_interactions": 3,
|
||||
"new_reactions": 0,
|
||||
"engagement_score": 7,
|
||||
"updated_at": "2026-04-25T03:00:00Z",
|
||||
"activity": {"new_comments": 3},
|
||||
},
|
||||
{
|
||||
"number": 22,
|
||||
"title": "Windows computer use tool fails to click buttons",
|
||||
"description": "Computer-use workflow failure",
|
||||
"url": "https://github.com/openai/codex/issues/22",
|
||||
"labels": ["app", "bug"],
|
||||
"owner_labels": ["app"],
|
||||
"kind_labels": ["bug"],
|
||||
"attention": False,
|
||||
"attention_level": 0,
|
||||
"attention_marker": "",
|
||||
"user_interactions": 3,
|
||||
"new_reactions": 0,
|
||||
"engagement_score": 6,
|
||||
"updated_at": "2026-04-25T02:00:00Z",
|
||||
"activity": {"new_comments": 3},
|
||||
},
|
||||
]
|
||||
|
||||
rows = collect_issue_digest.summary_inputs(issues, ref_map={20: 1, 21: 2, 22: 3})
|
||||
|
||||
assert rows == [
|
||||
{
|
||||
"ref": 1,
|
||||
"ref_markdown": "[1](https://github.com/openai/codex/issues/20)",
|
||||
"number": 20,
|
||||
"title": "Windows app Browser Use external navigation fails",
|
||||
"description": "Browser Use navigation or app-server failure",
|
||||
"url": "https://github.com/openai/codex/issues/20",
|
||||
"labels": ["app", "bug"],
|
||||
"owner_labels": ["app"],
|
||||
"kind_labels": ["bug"],
|
||||
"state": "",
|
||||
"attention_marker": "",
|
||||
"interactions": 3,
|
||||
"new_comments": 2,
|
||||
"new_reactions": 1,
|
||||
"new_upvotes": 0,
|
||||
"current_reactions": 0,
|
||||
},
|
||||
{
|
||||
"ref": 2,
|
||||
"ref_markdown": "[2](https://github.com/openai/codex/issues/21)",
|
||||
"number": 21,
|
||||
"title": "On Windows, cmake output waits until timeout",
|
||||
"description": "Windows command timeout/capture problem",
|
||||
"url": "https://github.com/openai/codex/issues/21",
|
||||
"labels": ["app", "bug"],
|
||||
"owner_labels": ["app"],
|
||||
"kind_labels": ["bug"],
|
||||
"state": "",
|
||||
"attention_marker": "",
|
||||
"interactions": 3,
|
||||
"new_comments": 3,
|
||||
"new_reactions": 0,
|
||||
"new_upvotes": 0,
|
||||
"current_reactions": 0,
|
||||
},
|
||||
{
|
||||
"ref": 3,
|
||||
"ref_markdown": "[3](https://github.com/openai/codex/issues/22)",
|
||||
"number": 22,
|
||||
"title": "Windows computer use tool fails to click buttons",
|
||||
"description": "Computer-use workflow failure",
|
||||
"url": "https://github.com/openai/codex/issues/22",
|
||||
"labels": ["app", "bug"],
|
||||
"owner_labels": ["app"],
|
||||
"kind_labels": ["bug"],
|
||||
"state": "",
|
||||
"attention_marker": "",
|
||||
"interactions": 3,
|
||||
"new_comments": 3,
|
||||
"new_reactions": 0,
|
||||
"new_upvotes": 0,
|
||||
"current_reactions": 0,
|
||||
},
|
||||
]
|
||||
@@ -4,9 +4,11 @@ ARG TZ
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG NODE_MAJOR=22
|
||||
ARG RUST_TOOLCHAIN=1.92.0
|
||||
ARG CODEX_NPM_VERSION=latest
|
||||
# Keep this in sync with .devcontainer/codex-install/package.json and pnpm-lock.yaml.
|
||||
ARG CODEX_NPM_VERSION=0.121.0
|
||||
|
||||
ENV TZ="$TZ"
|
||||
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
@@ -43,12 +45,18 @@ RUN apt-get update \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY .devcontainer/codex-install/package.json \
|
||||
.devcontainer/codex-install/pnpm-lock.yaml \
|
||||
.devcontainer/codex-install/pnpm-workspace.yaml \
|
||||
/opt/codex-install/
|
||||
|
||||
RUN curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& npm install -g corepack@latest "@openai/codex@${CODEX_NPM_VERSION}" \
|
||||
&& corepack enable \
|
||||
&& corepack prepare pnpm@10.28.2 --activate \
|
||||
&& test "$(node -p "require('/opt/codex-install/package.json').dependencies['@openai/codex']")" = "${CODEX_NPM_VERSION}" \
|
||||
&& cd /opt/codex-install \
|
||||
&& corepack pnpm install --prod --frozen-lockfile \
|
||||
&& ln -s /opt/codex-install/node_modules/.bin/codex /usr/local/bin/codex \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
13
.devcontainer/codex-install/package.json
Normal file
13
.devcontainer/codex-install/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "codex-devcontainer-install",
|
||||
"private": true,
|
||||
"description": "Locked Codex CLI install boundary for the secure devcontainer.",
|
||||
"dependencies": {
|
||||
"@openai/codex": "0.121.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22",
|
||||
"pnpm": ">=10.33.0"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
|
||||
}
|
||||
85
.devcontainer/codex-install/pnpm-lock.yaml
generated
Normal file
85
.devcontainer/codex-install/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,85 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@openai/codex':
|
||||
specifier: 0.121.0
|
||||
version: 0.121.0
|
||||
|
||||
packages:
|
||||
|
||||
'@openai/codex@0.121.0':
|
||||
resolution: {integrity: sha512-kCJ2NeATd4QBQRmqV04ymdN1ZU3MSwnJQDm/KzjpuzGvCuUVEn7no/T2mRyxQ2x77AACqriNOyPPoM/yufyvNg==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
'@openai/codex@0.121.0-darwin-arm64':
|
||||
resolution: {integrity: sha512-ZyBqIB6Fb4I0hGb/h65Vu7ePYjHSmGiqqfm+/1djEuxDPkqjfi4wkxYxNYNY+6najyNGN4UijOSTTf19eDCrqw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@openai/codex@0.121.0-darwin-x64':
|
||||
resolution: {integrity: sha512-1/OAtdkAZ5yPI3xqaEFlHuPziS1yCqL2gOZdswE7HTmmwpIxi6Z3FCo60JWDPluIp89z4tftdjq73/OCN0YVcw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@openai/codex@0.121.0-linux-arm64':
|
||||
resolution: {integrity: sha512-2UgMmdo237o7SCMsfb529cOSEM2HFUgN6OBkv5SBLwfNY1NO2Ex6JnUjlppEXlX6/4cXfZ5qjDghVz5j/+B9zw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@openai/codex@0.121.0-linux-x64':
|
||||
resolution: {integrity: sha512-vlpNJXIqss800J+32Vy7TUZzv31n61b45OLxmsVQGFkTNLJcjFrj9jDUC7I62eC4F16gLioilefNfv4CdJQOEw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@openai/codex@0.121.0-win32-arm64':
|
||||
resolution: {integrity: sha512-m88q4f3XI5npn1t6OG0nWGHWWAjO5FgjRwxh4hdujbLO6t9CiCNfhfPZIOSsoATbrCNwLC+6S77m3cjbNToPNg==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@openai/codex@0.121.0-win32-x64':
|
||||
resolution: {integrity: sha512-Fp0ecVOyM+VcBi/y4HVvRzhifO9YqRiHzhV3rhtAppC7flh22WPguLC4kmvXYAR0p3RPzbo35M2CedWnkOT+cw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
snapshots:
|
||||
|
||||
'@openai/codex@0.121.0':
|
||||
optionalDependencies:
|
||||
'@openai/codex-darwin-arm64': '@openai/codex@0.121.0-darwin-arm64'
|
||||
'@openai/codex-darwin-x64': '@openai/codex@0.121.0-darwin-x64'
|
||||
'@openai/codex-linux-arm64': '@openai/codex@0.121.0-linux-arm64'
|
||||
'@openai/codex-linux-x64': '@openai/codex@0.121.0-linux-x64'
|
||||
'@openai/codex-win32-arm64': '@openai/codex@0.121.0-win32-arm64'
|
||||
'@openai/codex-win32-x64': '@openai/codex@0.121.0-win32-x64'
|
||||
|
||||
'@openai/codex@0.121.0-darwin-arm64':
|
||||
optional: true
|
||||
|
||||
'@openai/codex@0.121.0-darwin-x64':
|
||||
optional: true
|
||||
|
||||
'@openai/codex@0.121.0-linux-arm64':
|
||||
optional: true
|
||||
|
||||
'@openai/codex@0.121.0-linux-x64':
|
||||
optional: true
|
||||
|
||||
'@openai/codex@0.121.0-win32-arm64':
|
||||
optional: true
|
||||
|
||||
'@openai/codex@0.121.0-win32-x64':
|
||||
optional: true
|
||||
12
.devcontainer/codex-install/pnpm-workspace.yaml
Normal file
12
.devcontainer/codex-install/pnpm-workspace.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
packages:
|
||||
- "."
|
||||
|
||||
minimumReleaseAge: 10080
|
||||
minimumReleaseAgeExclude: []
|
||||
|
||||
blockExoticSubdeps: true
|
||||
strictDepBuilds: true
|
||||
trustPolicy: no-downgrade
|
||||
trustPolicyIgnoreAfter: 10080
|
||||
trustPolicyExclude: []
|
||||
allowBuilds: {}
|
||||
@@ -8,7 +8,7 @@
|
||||
"TZ": "${localEnv:TZ:UTC}",
|
||||
"NODE_MAJOR": "22",
|
||||
"RUST_TOOLCHAIN": "1.92.0",
|
||||
"CODEX_NPM_VERSION": "latest"
|
||||
"CODEX_NPM_VERSION": "0.121.0"
|
||||
}
|
||||
},
|
||||
"runArgs": [
|
||||
|
||||
6
.github/actions/linux-code-sign/action.yml
vendored
6
.github/actions/linux-code-sign/action.yml
vendored
@@ -7,6 +7,9 @@ inputs:
|
||||
artifacts-dir:
|
||||
description: Absolute path to the directory containing built binaries to sign.
|
||||
required: true
|
||||
binaries:
|
||||
description: Space-delimited binary basenames to sign.
|
||||
default: "codex codex-responses-api-proxy"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -18,6 +21,7 @@ runs:
|
||||
shell: bash
|
||||
env:
|
||||
ARTIFACTS_DIR: ${{ inputs.artifacts-dir }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
COSIGN_EXPERIMENTAL: "1"
|
||||
COSIGN_YES: "true"
|
||||
COSIGN_OIDC_CLIENT_ID: "sigstore"
|
||||
@@ -31,7 +35,7 @@ runs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for binary in codex codex-responses-api-proxy; do
|
||||
for binary in ${BINARIES}; do
|
||||
artifact="${dest}/${binary}"
|
||||
if [[ ! -f "$artifact" ]]; then
|
||||
echo "Binary $artifact not found"
|
||||
|
||||
12
.github/actions/macos-code-sign/action.yml
vendored
12
.github/actions/macos-code-sign/action.yml
vendored
@@ -4,6 +4,9 @@ inputs:
|
||||
target:
|
||||
description: Rust compilation target triple (e.g. aarch64-apple-darwin).
|
||||
required: true
|
||||
binaries:
|
||||
description: Space-delimited binary basenames to sign and notarize.
|
||||
default: "codex codex-responses-api-proxy"
|
||||
sign-binaries:
|
||||
description: Whether to sign and notarize the macOS binaries.
|
||||
required: false
|
||||
@@ -119,6 +122,7 @@ runs:
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
@@ -134,7 +138,7 @@ runs:
|
||||
|
||||
entitlements_path="$GITHUB_ACTION_PATH/codex.entitlements.plist"
|
||||
|
||||
for binary in codex codex-responses-api-proxy; do
|
||||
for binary in ${BINARIES}; do
|
||||
path="codex-rs/target/${TARGET}/release/${binary}"
|
||||
codesign --force --options runtime --timestamp --entitlements "$entitlements_path" --sign "$APPLE_CODESIGN_IDENTITY" "${keychain_args[@]}" "$path"
|
||||
done
|
||||
@@ -144,6 +148,7 @@ runs:
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
APPLE_NOTARIZATION_KEY_P8: ${{ inputs.apple-notarization-key-p8 }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ inputs.apple-notarization-key-id }}
|
||||
APPLE_NOTARIZATION_ISSUER_ID: ${{ inputs.apple-notarization-issuer-id }}
|
||||
@@ -182,8 +187,9 @@ runs:
|
||||
notarize_submission "$binary" "$archive_path" "$notary_key_path"
|
||||
}
|
||||
|
||||
notarize_binary "codex"
|
||||
notarize_binary "codex-responses-api-proxy"
|
||||
for binary in ${BINARIES}; do
|
||||
notarize_binary "${binary}"
|
||||
done
|
||||
|
||||
- name: Sign and notarize macOS dmg
|
||||
if: ${{ inputs.sign-dmg == 'true' }}
|
||||
|
||||
@@ -2,15 +2,7 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.application-identifier</key>
|
||||
<string>2DC432GLL2.com.openai.codex</string>
|
||||
<key>com.apple.developer.team-identifier</key>
|
||||
<string>2DC432GLL2</string>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>2DC432GLL2.com.openai.codex</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
2
.github/actions/prepare-bazel-ci/action.yml
vendored
2
.github/actions/prepare-bazel-ci/action.yml
vendored
@@ -8,7 +8,7 @@ inputs:
|
||||
description: Logical namespace used to keep concurrent Bazel jobs from reserving the same repository cache key.
|
||||
required: true
|
||||
install-test-prereqs:
|
||||
description: Install Node.js and DotSlash for Bazel-backed test jobs.
|
||||
description: Install DotSlash for Bazel-backed test jobs.
|
||||
required: false
|
||||
default: "false"
|
||||
outputs:
|
||||
|
||||
15
.github/actions/setup-bazel-ci/action.yml
vendored
15
.github/actions/setup-bazel-ci/action.yml
vendored
@@ -5,7 +5,7 @@ inputs:
|
||||
description: Target triple used for cache namespacing.
|
||||
required: true
|
||||
install-test-prereqs:
|
||||
description: Install Node.js and DotSlash for Bazel-backed test jobs.
|
||||
description: Install DotSlash for Bazel-backed test jobs.
|
||||
required: false
|
||||
default: "false"
|
||||
outputs:
|
||||
@@ -16,12 +16,6 @@ outputs:
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set up Node.js for js_repl tests
|
||||
if: inputs.install-test-prereqs == 'true'
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version-file: codex-rs/node-version.txt
|
||||
|
||||
# Some integration tests rely on DotSlash being installed.
|
||||
# See https://github.com/openai/codex/pull/7617.
|
||||
- name: Install DotSlash
|
||||
@@ -39,7 +33,7 @@ runs:
|
||||
run: Copy-Item (Get-Command dotslash).Source -Destination "$env:LOCALAPPDATA\Microsoft\WindowsApps\dotslash.exe"
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@b39c379c82683a5f25d34f0d062761f62693e0b2 # v3
|
||||
uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
|
||||
|
||||
- name: Configure Bazel repository cache
|
||||
id: configure_bazel_repository_cache
|
||||
@@ -122,6 +116,11 @@ runs:
|
||||
}
|
||||
}
|
||||
|
||||
- name: Compute cache-stable Windows Bazel PATH
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: ./.github/scripts/compute-bazel-windows-path.ps1
|
||||
|
||||
- name: Enable Git long paths (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
|
||||
26
.github/actions/windows-code-sign/action.yml
vendored
26
.github/actions/windows-code-sign/action.yml
vendored
@@ -4,6 +4,9 @@ inputs:
|
||||
target:
|
||||
description: Target triple for the artifacts to sign.
|
||||
required: true
|
||||
binaries:
|
||||
description: Space-delimited binary basenames to sign.
|
||||
default: "codex codex-responses-api-proxy codex-windows-sandbox-setup codex-command-runner"
|
||||
client-id:
|
||||
description: Azure Trusted Signing client ID.
|
||||
required: true
|
||||
@@ -33,6 +36,23 @@ runs:
|
||||
tenant-id: ${{ inputs.tenant-id }}
|
||||
subscription-id: ${{ inputs.subscription-id }}
|
||||
|
||||
- name: Prepare file list
|
||||
id: prepare
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
BINARIES: ${{ inputs.binaries }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
{
|
||||
echo "files<<EOF"
|
||||
for binary in ${BINARIES}; do
|
||||
echo "${GITHUB_WORKSPACE}/codex-rs/target/${TARGET}/release/${binary}.exe"
|
||||
done
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Sign Windows binaries with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@1d365fec12862c4aa68fcac418143d73f0cea293 # v0
|
||||
with:
|
||||
@@ -50,8 +70,4 @@ runs:
|
||||
exclude-azure-developer-cli-credential: true
|
||||
exclude-interactive-browser-credential: true
|
||||
cache-dependencies: false
|
||||
files: |
|
||||
${{ github.workspace }}/codex-rs/target/${{ inputs.target }}/release/codex.exe
|
||||
${{ github.workspace }}/codex-rs/target/${{ inputs.target }}/release/codex-responses-api-proxy.exe
|
||||
${{ github.workspace }}/codex-rs/target/${{ inputs.target }}/release/codex-windows-sandbox-setup.exe
|
||||
${{ github.workspace }}/codex-rs/target/${{ inputs.target }}/release/codex-command-runner.exe
|
||||
files: ${{ steps.prepare.outputs.files }}
|
||||
|
||||
28
.github/dotslash-config.json
vendored
28
.github/dotslash-config.json
vendored
@@ -28,6 +28,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codex-app-server": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
"regex": "^codex-app-server-aarch64-apple-darwin\\.zst$",
|
||||
"path": "codex-app-server"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"regex": "^codex-app-server-x86_64-apple-darwin\\.zst$",
|
||||
"path": "codex-app-server"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"regex": "^codex-app-server-x86_64-unknown-linux-musl\\.zst$",
|
||||
"path": "codex-app-server"
|
||||
},
|
||||
"linux-aarch64": {
|
||||
"regex": "^codex-app-server-aarch64-unknown-linux-musl\\.zst$",
|
||||
"path": "codex-app-server"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
"regex": "^codex-app-server-x86_64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-app-server.exe"
|
||||
},
|
||||
"windows-aarch64": {
|
||||
"regex": "^codex-app-server-aarch64-pc-windows-msvc\\.exe\\.zst$",
|
||||
"path": "codex-app-server.exe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codex-responses-api-proxy": {
|
||||
"platforms": {
|
||||
"macos-aarch64": {
|
||||
|
||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -1,6 +1,6 @@
|
||||
# External (non-OpenAI) Pull Request Requirements
|
||||
|
||||
Before opening this Pull Request, please read the dedicated "Contributing" markdown file or your PR may be closed:
|
||||
External code contributions are by invitation only. Please read the dedicated "Contributing" markdown file for details:
|
||||
https://github.com/openai/codex/blob/main/docs/contributing.md
|
||||
|
||||
If your PR conforms to our contribution guidelines, replace this text with a detailed and high quality description of your changes.
|
||||
|
||||
105
.github/scripts/compute-bazel-windows-path.ps1
vendored
Normal file
105
.github/scripts/compute-bazel-windows-path.ps1
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<#
|
||||
BuildBuddy cache keys include the action and test environment, so Bazel should
|
||||
not inherit the full hosted-runner PATH on Windows. That PATH includes volatile
|
||||
tool entries, such as Maven, that can change independently of this repo and
|
||||
cause avoidable cache misses.
|
||||
|
||||
This script derives a smaller, cache-stable PATH that keeps the Windows
|
||||
toolchain entries Bazel-backed CI tasks need: MSVC and Windows SDK paths, Git,
|
||||
PowerShell, Node, Python, DotSlash, and the standard Windows system
|
||||
directories.
|
||||
`setup-bazel-ci` runs this after exporting the MSVC environment, and the script
|
||||
publishes the result via `GITHUB_ENV` as `CODEX_BAZEL_WINDOWS_PATH` so later
|
||||
steps can pass that explicit PATH to Bazel.
|
||||
#>
|
||||
|
||||
$stablePathEntries = New-Object System.Collections.Generic.List[string]
|
||||
$seenEntries = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||
$windowsAppsPath = if ([string]::IsNullOrWhiteSpace($env:LOCALAPPDATA)) {
|
||||
$null
|
||||
} else {
|
||||
"$($env:LOCALAPPDATA)\Microsoft\WindowsApps"
|
||||
}
|
||||
$windowsDir = if ($env:WINDIR) {
|
||||
$env:WINDIR
|
||||
} elseif ($env:SystemRoot) {
|
||||
$env:SystemRoot
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
function Add-StablePathEntry {
|
||||
param([string]$PathEntry)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($PathEntry)) {
|
||||
return
|
||||
}
|
||||
|
||||
if ($seenEntries.Add($PathEntry)) {
|
||||
[void]$stablePathEntries.Add($PathEntry)
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pathEntry in ($env:PATH -split ';')) {
|
||||
if ([string]::IsNullOrWhiteSpace($pathEntry)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
$pathEntry -like '*Microsoft Visual Studio*' -or
|
||||
$pathEntry -like '*Windows Kits*' -or
|
||||
$pathEntry -like '*Microsoft SDKs*' -or
|
||||
$pathEntry -like 'C:\Program Files\Git\*' -or
|
||||
$pathEntry -like 'C:\Program Files\PowerShell\*' -or
|
||||
$pathEntry -like 'C:\hostedtoolcache\windows\node\*' -or
|
||||
$pathEntry -like 'C:\hostedtoolcache\windows\Python\*' -or
|
||||
$pathEntry -eq 'D:\a\_temp\install-dotslash\bin' -or
|
||||
($windowsDir -and ($pathEntry -eq $windowsDir -or $pathEntry -like "${windowsDir}\*"))
|
||||
) {
|
||||
Add-StablePathEntry $pathEntry
|
||||
}
|
||||
}
|
||||
|
||||
$gitCommand = Get-Command git -ErrorAction SilentlyContinue
|
||||
if ($gitCommand) {
|
||||
Add-StablePathEntry (Split-Path $gitCommand.Source -Parent)
|
||||
}
|
||||
|
||||
$nodeCommand = Get-Command node -ErrorAction SilentlyContinue
|
||||
if ($nodeCommand) {
|
||||
Add-StablePathEntry (Split-Path $nodeCommand.Source -Parent)
|
||||
}
|
||||
|
||||
$python3Command = Get-Command python3 -ErrorAction SilentlyContinue
|
||||
if ($python3Command) {
|
||||
Add-StablePathEntry (Split-Path $python3Command.Source -Parent)
|
||||
}
|
||||
|
||||
$pythonCommand = Get-Command python -ErrorAction SilentlyContinue
|
||||
if ($pythonCommand) {
|
||||
Add-StablePathEntry (Split-Path $pythonCommand.Source -Parent)
|
||||
}
|
||||
|
||||
$pwshCommand = Get-Command pwsh -ErrorAction SilentlyContinue
|
||||
if ($pwshCommand) {
|
||||
Add-StablePathEntry (Split-Path $pwshCommand.Source -Parent)
|
||||
}
|
||||
|
||||
if ($windowsAppsPath) {
|
||||
Add-StablePathEntry $windowsAppsPath
|
||||
}
|
||||
|
||||
if ($stablePathEntries.Count -eq 0) {
|
||||
throw 'Failed to derive cache-stable Windows PATH.'
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($env:GITHUB_ENV)) {
|
||||
throw 'GITHUB_ENV must be set.'
|
||||
}
|
||||
|
||||
$stablePath = $stablePathEntries -join ';'
|
||||
Write-Host 'Derived CODEX_BAZEL_WINDOWS_PATH entries:'
|
||||
foreach ($pathEntry in $stablePathEntries) {
|
||||
Write-Host " $pathEntry"
|
||||
}
|
||||
"CODEX_BAZEL_WINDOWS_PATH=$stablePath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
@@ -2,16 +2,6 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ci_config=ci-linux
|
||||
case "${RUNNER_OS:-}" in
|
||||
macOS)
|
||||
ci_config=ci-macos
|
||||
;;
|
||||
Windows)
|
||||
ci_config=ci-windows
|
||||
;;
|
||||
esac
|
||||
|
||||
bazel_lint_args=("$@")
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
has_host_platform_override=0
|
||||
@@ -44,29 +34,6 @@ if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
bazel_lint_args+=("--skip_incompatible_explicit_targets")
|
||||
fi
|
||||
|
||||
bazel_startup_args=()
|
||||
if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then
|
||||
bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}")
|
||||
fi
|
||||
|
||||
run_bazel() {
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
MSYS2_ARG_CONV_EXCL='*' bazel "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
bazel "$@"
|
||||
}
|
||||
|
||||
run_bazel_with_startup_args() {
|
||||
if [[ ${#bazel_startup_args[@]} -gt 0 ]]; then
|
||||
run_bazel "${bazel_startup_args[@]}" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
run_bazel "$@"
|
||||
}
|
||||
|
||||
read_query_labels() {
|
||||
local query="$1"
|
||||
local query_stdout
|
||||
@@ -74,12 +41,10 @@ read_query_labels() {
|
||||
query_stdout="$(mktemp)"
|
||||
query_stderr="$(mktemp)"
|
||||
|
||||
if ! run_bazel_with_startup_args \
|
||||
--noexperimental_remote_repo_contents_cache \
|
||||
query \
|
||||
if ! ./.github/scripts/run-bazel-query-ci.sh \
|
||||
--keep_going \
|
||||
--output=label \
|
||||
"$query" >"$query_stdout" 2>"$query_stderr"; then
|
||||
-- "$query" >"$query_stdout" 2>"$query_stderr"; then
|
||||
cat "$query_stderr" >&2
|
||||
rm -f "$query_stdout" "$query_stderr"
|
||||
exit 1
|
||||
|
||||
29
.github/scripts/run-bazel-ci.sh
vendored
29
.github/scripts/run-bazel-ci.sh
vendored
@@ -4,7 +4,6 @@ set -euo pipefail
|
||||
|
||||
print_failed_bazel_test_logs=0
|
||||
print_failed_bazel_action_summary=0
|
||||
use_node_test_env=0
|
||||
remote_download_toplevel=0
|
||||
windows_msvc_host_platform=0
|
||||
|
||||
@@ -18,10 +17,6 @@ while [[ $# -gt 0 ]]; do
|
||||
print_failed_bazel_action_summary=1
|
||||
shift
|
||||
;;
|
||||
--use-node-test-env)
|
||||
use_node_test_env=1
|
||||
shift
|
||||
;;
|
||||
--remote-download-toplevel)
|
||||
remote_download_toplevel=1
|
||||
shift
|
||||
@@ -42,7 +37,7 @@ while [[ $# -gt 0 ]]; do
|
||||
done
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "Usage: $0 [--print-failed-test-logs] [--print-failed-action-summary] [--use-node-test-env] [--remote-download-toplevel] [--windows-msvc-host-platform] -- <bazel args> -- <targets>" >&2
|
||||
echo "Usage: $0 [--print-failed-test-logs] [--print-failed-action-summary] [--remote-download-toplevel] [--windows-msvc-host-platform] -- <bazel args> -- <targets>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -249,16 +244,6 @@ if [[ ${#bazel_args[@]} -eq 0 || ${#bazel_targets[@]} -eq 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $use_node_test_env -eq 1 ]]; then
|
||||
# Bazel test sandboxes on macOS may resolve an older Homebrew `node`
|
||||
# before the `actions/setup-node` runtime on PATH.
|
||||
node_bin="$(which node)"
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
node_bin="$(cygpath -w "${node_bin}")"
|
||||
fi
|
||||
bazel_args+=("--test_env=CODEX_JS_REPL_NODE_PATH=${node_bin}")
|
||||
fi
|
||||
|
||||
post_config_bazel_args=()
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" && $windows_msvc_host_platform -eq 1 ]]; then
|
||||
has_host_platform_override=0
|
||||
@@ -306,7 +291,6 @@ if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
INCLUDE
|
||||
LIB
|
||||
LIBPATH
|
||||
PATH
|
||||
UCRTVersion
|
||||
UniversalCRTSdkDir
|
||||
VCINSTALLDIR
|
||||
@@ -323,6 +307,17 @@ if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
post_config_bazel_args+=("--action_env=${env_var}" "--host_action_env=${env_var}")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "${CODEX_BAZEL_WINDOWS_PATH:-}" ]]; then
|
||||
echo "CODEX_BAZEL_WINDOWS_PATH must be set for Windows Bazel CI." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
post_config_bazel_args+=(
|
||||
"--action_env=PATH=${CODEX_BAZEL_WINDOWS_PATH}"
|
||||
"--host_action_env=PATH=${CODEX_BAZEL_WINDOWS_PATH}"
|
||||
"--test_env=PATH=${CODEX_BAZEL_WINDOWS_PATH}"
|
||||
)
|
||||
fi
|
||||
|
||||
bazel_console_log="$(mktemp)"
|
||||
|
||||
75
.github/scripts/run-bazel-query-ci.sh
vendored
Executable file
75
.github/scripts/run-bazel-query-ci.sh
vendored
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Run Bazel queries with the same CI startup settings as the main build/test
|
||||
# invocation so target-discovery queries can reuse the same Bazel server.
|
||||
|
||||
query_args=()
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
query_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $0 [<bazel query args>...] -- <query expression>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
query_expression="$1"
|
||||
|
||||
ci_config=ci-linux
|
||||
case "${RUNNER_OS:-}" in
|
||||
macOS)
|
||||
ci_config=ci-macos
|
||||
;;
|
||||
Windows)
|
||||
ci_config=ci-windows
|
||||
;;
|
||||
esac
|
||||
|
||||
bazel_startup_args=()
|
||||
if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then
|
||||
bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}")
|
||||
fi
|
||||
|
||||
run_bazel() {
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
MSYS2_ARG_CONV_EXCL='*' bazel "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
bazel "$@"
|
||||
}
|
||||
|
||||
bazel_query_args=(--noexperimental_remote_repo_contents_cache query)
|
||||
if [[ -n "${BUILDBUDDY_API_KEY:-}" ]]; then
|
||||
bazel_query_args+=(
|
||||
"--config=${ci_config}"
|
||||
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ -n "${BAZEL_REPO_CONTENTS_CACHE:-}" ]]; then
|
||||
bazel_query_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}")
|
||||
fi
|
||||
|
||||
if [[ -n "${BAZEL_REPOSITORY_CACHE:-}" ]]; then
|
||||
bazel_query_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}")
|
||||
fi
|
||||
|
||||
bazel_query_args+=("${query_args[@]}" "$query_expression")
|
||||
|
||||
if (( ${#bazel_startup_args[@]} > 0 )); then
|
||||
run_bazel "${bazel_startup_args[@]}" "${bazel_query_args[@]}"
|
||||
else
|
||||
run_bazel "${bazel_query_args[@]}"
|
||||
fi
|
||||
18
.github/workflows/Dockerfile.bazel
vendored
18
.github/workflows/Dockerfile.bazel
vendored
@@ -8,25 +8,9 @@ FROM ubuntu:24.04
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl git python3 ca-certificates xz-utils && \
|
||||
curl git python3 ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY codex-rs/node-version.txt /tmp/node-version.txt
|
||||
|
||||
RUN set -eux; \
|
||||
node_arch="$(dpkg --print-architecture)"; \
|
||||
case "${node_arch}" in \
|
||||
amd64) node_dist_arch="x64" ;; \
|
||||
arm64) node_dist_arch="arm64" ;; \
|
||||
*) echo "unsupported architecture: ${node_arch}"; exit 1 ;; \
|
||||
esac; \
|
||||
node_version="$(tr -d '[:space:]' </tmp/node-version.txt)"; \
|
||||
curl -fsSLO "https://nodejs.org/dist/v${node_version}/node-v${node_version}-linux-${node_dist_arch}.tar.xz"; \
|
||||
tar -xJf "node-v${node_version}-linux-${node_dist_arch}.tar.xz" -C /usr/local --strip-components=1; \
|
||||
rm "node-v${node_version}-linux-${node_dist_arch}.tar.xz" /tmp/node-version.txt; \
|
||||
node --version; \
|
||||
npm --version
|
||||
|
||||
# Install dotslash.
|
||||
RUN curl -LSfs "https://github.com/facebook/dotslash/releases/download/v0.5.8/dotslash-ubuntu-22.04.$(uname -m).tar.gz" | tar fxz - -C /usr/local/bin
|
||||
|
||||
|
||||
8
.github/workflows/bazel.yml
vendored
8
.github/workflows/bazel.yml
vendored
@@ -17,6 +17,13 @@ concurrency:
|
||||
cancel-in-progress: ${{ github.ref_name != 'main' }}
|
||||
jobs:
|
||||
test:
|
||||
# Even though a no-cache-hit Windows build seems to exceed the 30-minute
|
||||
# limit on occasion, the more common reason for exceeding the limit is a
|
||||
# true test failure in a rust_test() marked "flaky" that gets run 3x.
|
||||
# In that case, extra time generally does not give us more signal.
|
||||
#
|
||||
# Ultimately we need true distributed builds (e.g.,
|
||||
# https://www.buildbuddy.io/docs/rbe-setup/) to speed things up.
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -85,7 +92,6 @@ jobs:
|
||||
|
||||
bazel_wrapper_args=(
|
||||
--print-failed-test-logs
|
||||
--use-node-test-env
|
||||
)
|
||||
bazel_test_args=(
|
||||
test
|
||||
|
||||
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -45,11 +45,16 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Use a rust-release version that includes all native binaries.
|
||||
CODEX_VERSION=0.115.0
|
||||
# Use a recent successful rust-release run that published the full
|
||||
# cross-platform native payload required by the npm package layout.
|
||||
# Passing the workflow URL directly avoids relying on old rust-v*
|
||||
# branches remaining discoverable via `gh run list --branch ...`.
|
||||
CODEX_VERSION=0.125.0
|
||||
WORKFLOW_URL="https://github.com/openai/codex/actions/runs/24901475298"
|
||||
OUTPUT_DIR="${RUNNER_TEMP}"
|
||||
python3 ./scripts/stage_npm_packages.py \
|
||||
--release-version "$CODEX_VERSION" \
|
||||
--workflow-url "$WORKFLOW_URL" \
|
||||
--package codex \
|
||||
--output-dir "$OUTPUT_DIR"
|
||||
PACK_OUTPUT="${OUTPUT_DIR}/codex-npm-${CODEX_VERSION}.tgz"
|
||||
|
||||
4
.github/workflows/issue-deduplicator.yml
vendored
4
.github/workflows/issue-deduplicator.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
# .github/prompts/issue-deduplicator.txt file is obsolete and removed.
|
||||
- id: codex-all
|
||||
name: Find duplicates (pass 1, all issues)
|
||||
uses: openai/codex-action@0b91f4a2703c23df3102c3f0967d3c6db34eedef # v1
|
||||
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02 # v1.7
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
|
||||
- id: codex-open
|
||||
name: Find duplicates (pass 2, open issues)
|
||||
uses: openai/codex-action@0b91f4a2703c23df3102c3f0967d3c6db34eedef # v1
|
||||
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02 # v1.7
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
|
||||
2
.github/workflows/issue-labeler.yml
vendored
2
.github/workflows/issue-labeler.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- id: codex
|
||||
uses: openai/codex-action@0b91f4a2703c23df3102c3f0967d3c6db34eedef # v1
|
||||
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02 # v1.7
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
|
||||
4
.github/workflows/rust-ci-full.yml
vendored
4
.github/workflows/rust-ci-full.yml
vendored
@@ -560,10 +560,6 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Set up Node.js for js_repl tests
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version-file: codex-rs/node-version.txt
|
||||
- name: Install Linux build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
|
||||
62
.github/workflows/rust-release-windows.yml
vendored
62
.github/workflows/rust-release-windows.yml
vendored
@@ -40,28 +40,42 @@ jobs:
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
bundle: primary
|
||||
build_args: --bin codex --bin codex-responses-api-proxy
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
bundle: primary
|
||||
build_args: --bin codex --bin codex-responses-api-proxy
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
bundle: helpers
|
||||
build_args: --bin codex-windows-sandbox-setup --bin codex-command-runner
|
||||
binaries: "codex-windows-sandbox-setup codex-command-runner"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
bundle: helpers
|
||||
build_args: --bin codex-windows-sandbox-setup --bin codex-command-runner
|
||||
binaries: "codex-windows-sandbox-setup codex-command-runner"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
- runner: windows-x64
|
||||
target: x86_64-pc-windows-msvc
|
||||
bundle: app-server
|
||||
binaries: "codex-app-server"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
- runner: windows-arm64
|
||||
target: aarch64-pc-windows-msvc
|
||||
bundle: app-server
|
||||
binaries: "codex-app-server"
|
||||
runs_on:
|
||||
group: codex-runners
|
||||
labels: codex-windows-arm64
|
||||
@@ -89,7 +103,11 @@ jobs:
|
||||
- name: Cargo build (Windows binaries)
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build --target ${{ matrix.target }} --release --timings ${{ matrix.build_args }}
|
||||
build_args=()
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
build_args+=(--bin "$binary")
|
||||
done
|
||||
cargo build --target ${{ matrix.target }} --release --timings "${build_args[@]}"
|
||||
|
||||
- name: Upload Cargo timings
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
@@ -103,13 +121,9 @@ jobs:
|
||||
run: |
|
||||
output_dir="target/${{ matrix.target }}/release/staged-${{ matrix.bundle }}"
|
||||
mkdir -p "$output_dir"
|
||||
if [[ "${{ matrix.bundle }}" == "primary" ]]; then
|
||||
cp target/${{ matrix.target }}/release/codex.exe "$output_dir/codex.exe"
|
||||
cp target/${{ matrix.target }}/release/codex-responses-api-proxy.exe "$output_dir/codex-responses-api-proxy.exe"
|
||||
else
|
||||
cp target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe "$output_dir/codex-windows-sandbox-setup.exe"
|
||||
cp target/${{ matrix.target }}/release/codex-command-runner.exe "$output_dir/codex-command-runner.exe"
|
||||
fi
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
cp "target/${{ matrix.target }}/release/${binary}.exe" "$output_dir/${binary}.exe"
|
||||
done
|
||||
|
||||
- name: Upload Windows binaries
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
@@ -130,6 +144,8 @@ jobs:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
env:
|
||||
WINDOWS_BINARIES: "codex codex-responses-api-proxy codex-windows-sandbox-setup codex-command-runner codex-app-server"
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -161,19 +177,25 @@ jobs:
|
||||
name: windows-binaries-${{ matrix.target }}-helpers
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
|
||||
- name: Download prebuilt Windows app-server binary
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-app-server
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
|
||||
- name: Verify binaries
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ls -lh target/${{ matrix.target }}/release/codex.exe
|
||||
ls -lh target/${{ matrix.target }}/release/codex-responses-api-proxy.exe
|
||||
ls -lh target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe
|
||||
ls -lh target/${{ matrix.target }}/release/codex-command-runner.exe
|
||||
for binary in ${WINDOWS_BINARIES}; do
|
||||
ls -lh "target/${{ matrix.target }}/release/${binary}.exe"
|
||||
done
|
||||
|
||||
- name: Sign Windows binaries with Azure Trusted Signing
|
||||
uses: ./.github/actions/windows-code-sign
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
binaries: ${{ env.WINDOWS_BINARIES }}
|
||||
client-id: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TRUSTED_SIGNING_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_TRUSTED_SIGNING_SUBSCRIPTION_ID }}
|
||||
@@ -187,10 +209,10 @@ jobs:
|
||||
dest="dist/${{ matrix.target }}"
|
||||
mkdir -p "$dest"
|
||||
|
||||
cp target/${{ matrix.target }}/release/codex.exe "$dest/codex-${{ matrix.target }}.exe"
|
||||
cp target/${{ matrix.target }}/release/codex-responses-api-proxy.exe "$dest/codex-responses-api-proxy-${{ matrix.target }}.exe"
|
||||
cp target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe "$dest/codex-windows-sandbox-setup-${{ matrix.target }}.exe"
|
||||
cp target/${{ matrix.target }}/release/codex-command-runner.exe "$dest/codex-command-runner-${{ matrix.target }}.exe"
|
||||
for binary in ${WINDOWS_BINARIES}; do
|
||||
cp "target/${{ matrix.target }}/release/${binary}.exe" \
|
||||
"$dest/${binary}-${{ matrix.target }}.exe"
|
||||
done
|
||||
|
||||
- name: Install DotSlash
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
153
.github/workflows/rust-release.yml
vendored
153
.github/workflows/rust-release.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
build:
|
||||
needs: tag-check
|
||||
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
|
||||
name: Build - ${{ matrix.runner }} - ${{ matrix.target }} - ${{ matrix.bundle }}
|
||||
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
@@ -67,16 +67,53 @@ jobs:
|
||||
include:
|
||||
- runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
bundle: primary
|
||||
artifact_name: aarch64-apple-darwin
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
build_dmg: "true"
|
||||
- runner: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
bundle: app-server
|
||||
artifact_name: aarch64-apple-darwin-app-server
|
||||
binaries: "codex-app-server"
|
||||
build_dmg: "false"
|
||||
- runner: macos-15-xlarge
|
||||
target: x86_64-apple-darwin
|
||||
bundle: primary
|
||||
artifact_name: x86_64-apple-darwin
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
build_dmg: "true"
|
||||
- runner: macos-15-xlarge
|
||||
target: x86_64-apple-darwin
|
||||
bundle: app-server
|
||||
artifact_name: x86_64-apple-darwin-app-server
|
||||
binaries: "codex-app-server"
|
||||
build_dmg: "false"
|
||||
# Release artifacts intentionally ship MUSL-linked Linux binaries.
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-musl
|
||||
bundle: primary
|
||||
artifact_name: x86_64-unknown-linux-musl
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
build_dmg: "false"
|
||||
- runner: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
target: x86_64-unknown-linux-musl
|
||||
bundle: app-server
|
||||
artifact_name: x86_64-unknown-linux-musl-app-server
|
||||
binaries: "codex-app-server"
|
||||
build_dmg: "false"
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-musl
|
||||
bundle: primary
|
||||
artifact_name: aarch64-unknown-linux-musl
|
||||
binaries: "codex codex-responses-api-proxy"
|
||||
build_dmg: "false"
|
||||
- runner: ubuntu-24.04-arm
|
||||
target: aarch64-unknown-linux-gnu
|
||||
target: aarch64-unknown-linux-musl
|
||||
bundle: app-server
|
||||
artifact_name: aarch64-unknown-linux-musl-app-server
|
||||
binaries: "codex-app-server"
|
||||
build_dmg: "false"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
@@ -219,13 +256,17 @@ jobs:
|
||||
- name: Cargo build
|
||||
shell: bash
|
||||
run: |
|
||||
build_args=()
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
build_args+=(--bin "$binary")
|
||||
done
|
||||
echo "CARGO_PROFILE_RELEASE_LTO: ${CARGO_PROFILE_RELEASE_LTO}"
|
||||
cargo build --target ${{ matrix.target }} --release --timings --bin codex --bin codex-responses-api-proxy
|
||||
cargo build --target ${{ matrix.target }} --release --timings "${build_args[@]}"
|
||||
|
||||
- name: Upload Cargo timings
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: cargo-timings-rust-release-${{ matrix.target }}
|
||||
name: cargo-timings-rust-release-${{ matrix.target }}-${{ matrix.bundle }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
if-no-files-found: warn
|
||||
|
||||
@@ -235,12 +276,14 @@ jobs:
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
artifacts-dir: ${{ github.workspace }}/codex-rs/target/${{ matrix.target }}/release
|
||||
binaries: ${{ matrix.binaries }}
|
||||
|
||||
- if: ${{ runner.os == 'macOS' }}
|
||||
name: MacOS code signing (binaries)
|
||||
uses: ./.github/actions/macos-code-sign
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
binaries: ${{ matrix.binaries }}
|
||||
sign-binaries: "true"
|
||||
sign-dmg: "false"
|
||||
apple-certificate: ${{ secrets.APPLE_CERTIFICATE_P12 }}
|
||||
@@ -249,7 +292,7 @@ jobs:
|
||||
apple-notarization-key-id: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
apple-notarization-issuer-id: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
|
||||
|
||||
- if: ${{ runner.os == 'macOS' }}
|
||||
- if: ${{ runner.os == 'macOS' && matrix.build_dmg == 'true' }}
|
||||
name: Build macOS dmg
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -264,23 +307,17 @@ jobs:
|
||||
# The previous "MacOS code signing (binaries)" step signs + notarizes the
|
||||
# built artifacts in `${release_dir}`. This step packages *those same*
|
||||
# signed binaries into a dmg.
|
||||
codex_binary_path="${release_dir}/codex"
|
||||
proxy_binary_path="${release_dir}/codex-responses-api-proxy"
|
||||
|
||||
rm -rf "$dmg_root"
|
||||
mkdir -p "$dmg_root"
|
||||
|
||||
if [[ ! -f "$codex_binary_path" ]]; then
|
||||
echo "Binary $codex_binary_path not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$proxy_binary_path" ]]; then
|
||||
echo "Binary $proxy_binary_path not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ditto "$codex_binary_path" "${dmg_root}/codex"
|
||||
ditto "$proxy_binary_path" "${dmg_root}/codex-responses-api-proxy"
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
binary_path="${release_dir}/${binary}"
|
||||
if [[ ! -f "${binary_path}" ]]; then
|
||||
echo "Binary ${binary_path} not found"
|
||||
exit 1
|
||||
fi
|
||||
ditto "${binary_path}" "${dmg_root}/${binary}"
|
||||
done
|
||||
|
||||
rm -f "$dmg_path"
|
||||
hdiutil create \
|
||||
@@ -295,7 +332,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- if: ${{ runner.os == 'macOS' }}
|
||||
- if: ${{ runner.os == 'macOS' && matrix.build_dmg == 'true' }}
|
||||
name: MacOS code signing (dmg)
|
||||
uses: ./.github/actions/macos-code-sign
|
||||
with:
|
||||
@@ -314,15 +351,15 @@ jobs:
|
||||
dest="dist/${{ matrix.target }}"
|
||||
mkdir -p "$dest"
|
||||
|
||||
cp target/${{ matrix.target }}/release/codex "$dest/codex-${{ matrix.target }}"
|
||||
cp target/${{ matrix.target }}/release/codex-responses-api-proxy "$dest/codex-responses-api-proxy-${{ matrix.target }}"
|
||||
for binary in ${{ matrix.binaries }}; do
|
||||
cp "target/${{ matrix.target }}/release/${binary}" "$dest/${binary}-${{ matrix.target }}"
|
||||
if [[ "${{ matrix.target }}" == *linux* ]]; then
|
||||
cp "target/${{ matrix.target }}/release/${binary}.sigstore" \
|
||||
"$dest/${binary}-${{ matrix.target }}.sigstore"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${{ matrix.target }}" == *linux* ]]; then
|
||||
cp target/${{ matrix.target }}/release/codex.sigstore "$dest/codex-${{ matrix.target }}.sigstore"
|
||||
cp target/${{ matrix.target }}/release/codex-responses-api-proxy.sigstore "$dest/codex-responses-api-proxy-${{ matrix.target }}.sigstore"
|
||||
fi
|
||||
|
||||
if [[ "${{ matrix.target }}" == *apple-darwin ]]; then
|
||||
if [[ "${{ matrix.build_dmg }}" == "true" ]]; then
|
||||
cp target/${{ matrix.target }}/release/codex-${{ matrix.target }}.dmg "$dest/codex-${{ matrix.target }}.dmg"
|
||||
fi
|
||||
|
||||
@@ -364,7 +401,7 @@ jobs:
|
||||
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
name: ${{ matrix.artifact_name }}
|
||||
# Upload the per-binary .zst files as well as the new .tar.gz
|
||||
# equivalents we generated in the previous step.
|
||||
path: |
|
||||
@@ -614,11 +651,59 @@ jobs:
|
||||
prefix="${NPM_TAG}-"
|
||||
fi
|
||||
|
||||
root_tarball="dist/npm/codex-npm-${VERSION}.tgz"
|
||||
sdk_tarball="dist/npm/codex-sdk-npm-${VERSION}.tgz"
|
||||
# Keep this list in sync with CODEX_PLATFORM_PACKAGES in
|
||||
# codex-cli/scripts/build_npm_package.py. The root wrapper advances
|
||||
# @openai/codex@latest as soon as it publishes, so every platform
|
||||
# package it aliases must already exist in the registry first.
|
||||
platform_tarballs=(
|
||||
"dist/npm/codex-npm-linux-x64-${VERSION}.tgz"
|
||||
"dist/npm/codex-npm-linux-arm64-${VERSION}.tgz"
|
||||
"dist/npm/codex-npm-darwin-x64-${VERSION}.tgz"
|
||||
"dist/npm/codex-npm-darwin-arm64-${VERSION}.tgz"
|
||||
"dist/npm/codex-npm-win32-x64-${VERSION}.tgz"
|
||||
"dist/npm/codex-npm-win32-arm64-${VERSION}.tgz"
|
||||
)
|
||||
|
||||
for required_tarball in "${platform_tarballs[@]}" "${root_tarball}"; do
|
||||
if [[ ! -f "${required_tarball}" ]]; then
|
||||
echo "Missing npm tarball: ${required_tarball}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
shopt -s nullglob
|
||||
tarballs=(dist/npm/*-"${VERSION}".tgz)
|
||||
if [[ ${#tarballs[@]} -eq 0 ]]; then
|
||||
echo "No npm tarballs found in dist/npm for version ${VERSION}"
|
||||
exit 1
|
||||
other_tarballs=()
|
||||
for tarball in dist/npm/*-"${VERSION}".tgz; do
|
||||
if [[ "${tarball}" == "${root_tarball}" || "${tarball}" == "${sdk_tarball}" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
is_platform_tarball=false
|
||||
for platform_tarball in "${platform_tarballs[@]}"; do
|
||||
if [[ "${tarball}" == "${platform_tarball}" ]]; then
|
||||
is_platform_tarball=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${is_platform_tarball}" == true ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
other_tarballs+=("${tarball}")
|
||||
done
|
||||
|
||||
# Publish the platform packages before the root CLI wrapper. The root
|
||||
# wrapper advances @openai/codex@latest, so it should only publish
|
||||
# after the optional dependency versions it references exist.
|
||||
tarballs=(
|
||||
"${platform_tarballs[@]}"
|
||||
"${other_tarballs[@]}"
|
||||
"${root_tarball}"
|
||||
)
|
||||
if [[ -f "${sdk_tarball}" ]]; then
|
||||
tarballs+=("${sdk_tarball}")
|
||||
fi
|
||||
|
||||
for tarball in "${tarballs[@]}"; do
|
||||
|
||||
4
.github/workflows/rusty-v8-release.yml
vendored
4
.github/workflows/rusty-v8-release.yml
vendored
@@ -78,7 +78,9 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@b39c379c82683a5f25d34f0d062761f62693e0b2 # v3
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
|
||||
6
.github/workflows/v8-canary.yml
vendored
6
.github/workflows/v8-canary.yml
vendored
@@ -3,6 +3,7 @@ name: v8-canary
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/actions/setup-bazel-ci/**"
|
||||
- ".github/scripts/rusty_v8_bazel.py"
|
||||
- ".github/workflows/rusty-v8-release.yml"
|
||||
- ".github/workflows/v8-canary.yml"
|
||||
@@ -16,6 +17,7 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/actions/setup-bazel-ci/**"
|
||||
- ".github/scripts/rusty_v8_bazel.py"
|
||||
- ".github/workflows/rusty-v8-release.yml"
|
||||
- ".github/workflows/v8-canary.yml"
|
||||
@@ -75,7 +77,9 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@b39c379c82683a5f25d34f0d062761f62693e0b2 # v3
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -52,6 +52,7 @@ yarn-error.log*
|
||||
# env
|
||||
.env*
|
||||
!.env.example
|
||||
.venv/
|
||||
|
||||
# package
|
||||
*.tgz
|
||||
@@ -91,4 +92,3 @@ CHANGELOG.ignore.md
|
||||
# Python bytecode files
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
|
||||
1
MODULE.bazel.lock
generated
1
MODULE.bazel.lock
generated
@@ -1560,6 +1560,7 @@
|
||||
"system-deps_7.0.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"assert_matches\",\"req\":\"^1.5\"},{\"features\":[\"targets\"],\"name\":\"cfg-expr\",\"req\":\">=0.17, <0.21\"},{\"name\":\"heck\",\"req\":\"^0.5\"},{\"kind\":\"dev\",\"name\":\"itertools\",\"req\":\"^0.14\"},{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1\"},{\"name\":\"pkg-config\",\"req\":\"^0.3.25\"},{\"default_features\":false,\"features\":[\"parse\",\"std\"],\"name\":\"toml\",\"req\":\"^0.9\"},{\"name\":\"version-compare\",\"req\":\"^0.2\"}],\"features\":{}}",
|
||||
"tagptr_0.2.0": "{\"dependencies\":[],\"features\":{}}",
|
||||
"tar_0.4.44": "{\"dependencies\":[{\"name\":\"filetime\",\"req\":\"^0.2.8\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"},{\"name\":\"xattr\",\"optional\":true,\"req\":\"^1.1.3\",\"target\":\"cfg(unix)\"}],\"features\":{\"default\":[\"xattr\"]}}",
|
||||
"tar_0.4.45": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"astral-tokio-tar\",\"req\":\"^0.5\"},{\"name\":\"filetime\",\"req\":\"^0.2.8\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"features\":[\"small_rng\"],\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"},{\"features\":[\"macros\",\"rt\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-stream\",\"req\":\"^0.1\"},{\"name\":\"xattr\",\"optional\":true,\"req\":\"^1.1.3\",\"target\":\"cfg(unix)\"}],\"features\":{\"default\":[\"xattr\"]}}",
|
||||
"target-lexicon_0.13.3": "{\"dependencies\":[{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"arch_z80\":[],\"arch_zkasm\":[],\"default\":[],\"serde_support\":[\"serde\",\"std\"],\"std\":[]}}",
|
||||
"tempfile_3.27.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"name\":\"fastrand\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"name\":\"getrandom\",\"optional\":true,\"req\":\">=0.3.0, <0.5\",\"target\":\"cfg(any(unix, windows, target_os = \\\"wasi\\\"))\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"once_cell\",\"req\":\"^1.19.0\"},{\"features\":[\"fs\"],\"name\":\"rustix\",\"req\":\"^1.1.4\",\"target\":\"cfg(any(unix, target_os = \\\"wasi\\\"))\"},{\"features\":[\"Win32_Storage_FileSystem\",\"Win32_Foundation\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"getrandom\"],\"nightly\":[]}}",
|
||||
"temporal_capi_0.1.2": "{\"dependencies\":[{\"default_features\":false,\"name\":\"diplomat\",\"req\":\"^0.14.0\"},{\"default_features\":false,\"name\":\"diplomat-runtime\",\"req\":\"^0.14.0\"},{\"default_features\":false,\"features\":[\"unstable\"],\"name\":\"icu_calendar\",\"req\":\"^2.1.0\"},{\"name\":\"icu_locale\",\"req\":\"^2.1.0\"},{\"default_features\":false,\"name\":\"num-traits\",\"req\":\"^0.2.19\"},{\"default_features\":false,\"name\":\"temporal_rs\",\"req\":\"^0.1.2\"},{\"name\":\"timezone_provider\",\"req\":\"^0.1.2\"},{\"name\":\"writeable\",\"req\":\"^0.6.0\"},{\"name\":\"zoneinfo64\",\"optional\":true,\"req\":\"^0.2.0\"}],\"features\":{\"compiled_data\":[\"temporal_rs/compiled_data\"],\"zoneinfo64\":[\"dep:zoneinfo64\",\"timezone_provider/zoneinfo64\"]}}",
|
||||
|
||||
3
NOTICE
3
NOTICE
@@ -4,6 +4,3 @@ Copyright 2025 OpenAI
|
||||
This project includes code derived from [Ratatui](https://github.com/ratatui/ratatui), licensed under the MIT license.
|
||||
Copyright (c) 2016-2022 Florian Dehau
|
||||
Copyright (c) 2023-2025 The Ratatui Developers
|
||||
|
||||
This project includes Meriyah parser assets from [meriyah](https://github.com/meriyah/meriyah), licensed under the ISC license.
|
||||
Copyright (c) 2019 and later, KFlash and others.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</p>
|
||||
</br>
|
||||
If you want Codex in your code editor (VS Code, Cursor, Windsurf), <a href="https://developers.openai.com/codex/ide">install in your IDE.</a>
|
||||
</br>If you want the desktop app experience, run <code>codex app</code> or visit <a href="https://chatgpt.com/codex?app-landing-page=true">the Codex App page</a>.
|
||||
</br>If you want the desktop app experience on macOS or Windows, run <code>codex app</code> or visit <a href="https://chatgpt.com/codex?app-landing-page=true">the Codex App page</a>.
|
||||
</br>If you are looking for the <em>cloud-based agent</em> from OpenAI, <strong>Codex Web</strong>, go to <a href="https://chatgpt.com/codex">chatgpt.com/codex</a>.</p>
|
||||
|
||||
---
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
node_modules/
|
||||
@@ -1,59 +0,0 @@
|
||||
FROM node:24-slim
|
||||
|
||||
ARG TZ
|
||||
ENV TZ="$TZ"
|
||||
|
||||
# Install basic development tools, ca-certificates, and iptables/ipset, then clean up apt cache to reduce image size
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
aggregate \
|
||||
ca-certificates \
|
||||
curl \
|
||||
dnsutils \
|
||||
fzf \
|
||||
gh \
|
||||
git \
|
||||
gnupg2 \
|
||||
iproute2 \
|
||||
ipset \
|
||||
iptables \
|
||||
jq \
|
||||
less \
|
||||
man-db \
|
||||
procps \
|
||||
unzip \
|
||||
ripgrep \
|
||||
zsh \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Ensure default node user has access to /usr/local/share
|
||||
RUN mkdir -p /usr/local/share/npm-global && \
|
||||
chown -R node:node /usr/local/share
|
||||
|
||||
ARG USERNAME=node
|
||||
|
||||
# Set up non-root user
|
||||
USER node
|
||||
|
||||
# Install global packages
|
||||
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
|
||||
ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
||||
|
||||
# Install codex
|
||||
COPY dist/codex.tgz codex.tgz
|
||||
RUN npm install -g codex.tgz \
|
||||
&& npm cache clean --force \
|
||||
&& rm -rf /usr/local/share/npm-global/lib/node_modules/codex-cli/node_modules/.cache \
|
||||
&& rm -rf /usr/local/share/npm-global/lib/node_modules/codex-cli/tests \
|
||||
&& rm -rf /usr/local/share/npm-global/lib/node_modules/codex-cli/docs
|
||||
|
||||
# Inside the container we consider the environment already sufficiently locked
|
||||
# down, therefore instruct Codex CLI to allow running without sandboxing.
|
||||
ENV CODEX_UNSAFE_ALLOW_NO_SANDBOX=1
|
||||
|
||||
# Copy and set up firewall script as root.
|
||||
USER root
|
||||
COPY scripts/init_firewall.sh /usr/local/bin/
|
||||
RUN chmod 500 /usr/local/bin/init_firewall.sh
|
||||
|
||||
# Drop back to non-root.
|
||||
USER node
|
||||
@@ -18,5 +18,5 @@
|
||||
"url": "git+https://github.com/openai/codex.git",
|
||||
"directory": "codex-cli"
|
||||
},
|
||||
"packageManager": "pnpm@10.29.3+sha512.498e1fb4cca5aa06c1dcf2611e6fafc50972ffe7189998c409e90de74566444298ffe43e6cd2acdc775ba1aa7cc5e092a8b7054c811ba8c5770f84693d33d2dc"
|
||||
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(realpath "$(dirname "$0")")
|
||||
trap "popd >> /dev/null" EXIT
|
||||
pushd "$SCRIPT_DIR/.." >> /dev/null || {
|
||||
echo "Error: Failed to change directory to $SCRIPT_DIR/.."
|
||||
exit 1
|
||||
}
|
||||
pnpm install
|
||||
pnpm run build
|
||||
rm -rf ./dist/openai-codex-*.tgz
|
||||
pnpm pack --pack-destination ./dist
|
||||
mv ./dist/openai-codex-*.tgz ./dist/codex.tgz
|
||||
docker build -t codex -f "./Dockerfile" .
|
||||
@@ -1,6 +1,5 @@
|
||||
exports_files([
|
||||
"clippy.toml",
|
||||
"node-version.txt",
|
||||
])
|
||||
|
||||
filegroup(
|
||||
|
||||
136
codex-rs/Cargo.lock
generated
136
codex-rs/Cargo.lock
generated
@@ -1758,6 +1758,7 @@ dependencies = [
|
||||
"codex-protocol",
|
||||
"crypto_box",
|
||||
"ed25519-dalek",
|
||||
"jsonwebtoken",
|
||||
"pretty_assertions",
|
||||
"rand 0.9.3",
|
||||
"reqwest",
|
||||
@@ -1773,6 +1774,7 @@ dependencies = [
|
||||
"codex-app-server-protocol",
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-plugin",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
@@ -1840,6 +1842,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"codex-analytics",
|
||||
"codex-api",
|
||||
"codex-app-server-protocol",
|
||||
"codex-arg0",
|
||||
"codex-backend-client",
|
||||
@@ -1856,6 +1859,8 @@ dependencies = [
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-mcp",
|
||||
"codex-memories-write",
|
||||
"codex-model-provider",
|
||||
"codex-model-provider-info",
|
||||
"codex-models-manager",
|
||||
"codex-otel",
|
||||
@@ -1876,6 +1881,7 @@ dependencies = [
|
||||
"codex-utils-rustls-provider",
|
||||
"constant_time_eq 0.3.1",
|
||||
"core_test_support",
|
||||
"flate2",
|
||||
"futures",
|
||||
"gethostname",
|
||||
"hmac",
|
||||
@@ -1891,6 +1897,7 @@ dependencies = [
|
||||
"serial_test",
|
||||
"sha2",
|
||||
"shlex",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"time",
|
||||
@@ -2045,9 +2052,11 @@ name = "codex-backend-client"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"codex-api",
|
||||
"codex-backend-openapi-models",
|
||||
"codex-client",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-protocol",
|
||||
"pretty_assertions",
|
||||
"reqwest",
|
||||
@@ -2071,11 +2080,11 @@ dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"codex-app-server-protocol",
|
||||
"codex-config",
|
||||
"codex-connectors",
|
||||
"codex-core",
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-utils-cargo-bin",
|
||||
"codex-utils-cli",
|
||||
"pretty_assertions",
|
||||
@@ -2094,7 +2103,6 @@ dependencies = [
|
||||
"assert_matches",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"codex-api",
|
||||
"codex-app-server",
|
||||
"codex-app-server-protocol",
|
||||
"codex-app-server-test-client",
|
||||
@@ -2111,11 +2119,12 @@ dependencies = [
|
||||
"codex-login",
|
||||
"codex-mcp",
|
||||
"codex-mcp-server",
|
||||
"codex-model-provider",
|
||||
"codex-memories-write",
|
||||
"codex-models-manager",
|
||||
"codex-protocol",
|
||||
"codex-responses-api-proxy",
|
||||
"codex-rmcp-client",
|
||||
"codex-rollout-trace",
|
||||
"codex-sandboxing",
|
||||
"codex-state",
|
||||
"codex-stdio-to-uds",
|
||||
@@ -2203,7 +2212,6 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"clap",
|
||||
"codex-client",
|
||||
@@ -2212,6 +2220,7 @@ dependencies = [
|
||||
"codex-core",
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-tui",
|
||||
"codex-utils-cli",
|
||||
"crossterm",
|
||||
@@ -2236,6 +2245,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"codex-api",
|
||||
"codex-backend-client",
|
||||
"codex-git-utils",
|
||||
"serde",
|
||||
@@ -2280,15 +2290,20 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"codex-app-server-protocol",
|
||||
"codex-execpolicy",
|
||||
"codex-features",
|
||||
"codex-file-system",
|
||||
"codex-git-utils",
|
||||
"codex-model-provider-info",
|
||||
"codex-network-proxy",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-path",
|
||||
"core-foundation 0.9.4",
|
||||
"dns-lookup",
|
||||
"dunce",
|
||||
"futures",
|
||||
"gethostname",
|
||||
"libc",
|
||||
@@ -2312,6 +2327,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"wildmatch",
|
||||
"winapi-util",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2358,6 +2374,7 @@ dependencies = [
|
||||
"codex-hooks",
|
||||
"codex-login",
|
||||
"codex-mcp",
|
||||
"codex-memories-read",
|
||||
"codex-model-provider",
|
||||
"codex-model-provider-info",
|
||||
"codex-models-manager",
|
||||
@@ -2370,7 +2387,6 @@ dependencies = [
|
||||
"codex-rollout",
|
||||
"codex-rollout-trace",
|
||||
"codex-sandboxing",
|
||||
"codex-secrets",
|
||||
"codex-shell-command",
|
||||
"codex-shell-escalation",
|
||||
"codex-state",
|
||||
@@ -2392,7 +2408,6 @@ dependencies = [
|
||||
"codex-utils-string",
|
||||
"codex-utils-template",
|
||||
"codex-windows-sandbox",
|
||||
"core-foundation 0.9.4",
|
||||
"core_test_support",
|
||||
"csv",
|
||||
"ctor 0.6.3",
|
||||
@@ -2443,7 +2458,6 @@ dependencies = [
|
||||
"walkdir",
|
||||
"which 8.0.0",
|
||||
"whoami",
|
||||
"windows-sys 0.52.0",
|
||||
"wiremock",
|
||||
"zstd 0.13.3",
|
||||
]
|
||||
@@ -2460,17 +2474,20 @@ dependencies = [
|
||||
"codex-exec-server",
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-otel",
|
||||
"codex-plugin",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-plugins",
|
||||
"dirs",
|
||||
"flate2",
|
||||
"libc",
|
||||
"pretty_assertions",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
@@ -2491,6 +2508,7 @@ dependencies = [
|
||||
"codex-config",
|
||||
"codex-exec-server",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-otel",
|
||||
"codex-protocol",
|
||||
"codex-skills",
|
||||
@@ -2527,6 +2545,7 @@ dependencies = [
|
||||
name = "codex-device-key"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"p256",
|
||||
"pretty_assertions",
|
||||
@@ -2534,6 +2553,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -2549,6 +2569,7 @@ dependencies = [
|
||||
"codex-apply-patch",
|
||||
"codex-arg0",
|
||||
"codex-cloud-requirements",
|
||||
"codex-config",
|
||||
"codex-core",
|
||||
"codex-feedback",
|
||||
"codex-git-utils",
|
||||
@@ -2592,7 +2613,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"codex-app-server-protocol",
|
||||
"codex-client",
|
||||
"codex-config",
|
||||
"codex-file-system",
|
||||
"codex-protocol",
|
||||
"codex-sandboxing",
|
||||
"codex-test-binary-support",
|
||||
@@ -2703,14 +2724,23 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-file-system"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-git-utils"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_matches",
|
||||
"chrono",
|
||||
"codex-exec-server",
|
||||
"codex-file-system",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"futures",
|
||||
@@ -2770,7 +2800,6 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"clap",
|
||||
"codex-config",
|
||||
"codex-core",
|
||||
"codex-protocol",
|
||||
"codex-sandboxing",
|
||||
@@ -2849,15 +2878,16 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel",
|
||||
"codex-api",
|
||||
"codex-async-utils",
|
||||
"codex-config",
|
||||
"codex-exec-server",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-otel",
|
||||
"codex-plugin",
|
||||
"codex-protocol",
|
||||
"codex-rmcp-client",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-plugins",
|
||||
"futures",
|
||||
"pretty_assertions",
|
||||
@@ -2907,19 +2937,76 @@ dependencies = [
|
||||
"wiremock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-memories-read"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-protocol",
|
||||
"codex-shell-command",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-output-truncation",
|
||||
"codex-utils-template",
|
||||
"pretty_assertions",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-memories-write"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"codex-config",
|
||||
"codex-core",
|
||||
"codex-features",
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-models-manager",
|
||||
"codex-otel",
|
||||
"codex-protocol",
|
||||
"codex-rollout",
|
||||
"codex-rollout-trace",
|
||||
"codex-secrets",
|
||||
"codex-state",
|
||||
"codex-terminal-detection",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-output-truncation",
|
||||
"codex-utils-template",
|
||||
"core_test_support",
|
||||
"futures",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"wiremock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-model-provider"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"codex-agent-identity",
|
||||
"codex-api",
|
||||
"codex-aws-auth",
|
||||
"codex-client",
|
||||
"codex-feedback",
|
||||
"codex-login",
|
||||
"codex-model-provider-info",
|
||||
"codex-models-manager",
|
||||
"codex-otel",
|
||||
"codex-protocol",
|
||||
"codex-response-debug-context",
|
||||
"http 1.4.0",
|
||||
"pretty_assertions",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"wiremock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2943,32 +3030,21 @@ dependencies = [
|
||||
name = "codex-models-manager"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"codex-api",
|
||||
"codex-app-server-protocol",
|
||||
"codex-collaboration-mode-templates",
|
||||
"codex-config",
|
||||
"codex-feedback",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
"codex-model-provider-info",
|
||||
"codex-otel",
|
||||
"codex-protocol",
|
||||
"codex-response-debug-context",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-output-truncation",
|
||||
"codex-utils-template",
|
||||
"core_test_support",
|
||||
"http 1.4.0",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"wiremock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3108,6 +3184,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"ts-rs",
|
||||
"uuid",
|
||||
"wildmatch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3154,6 +3231,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"bytes",
|
||||
"codex-api",
|
||||
"codex-client",
|
||||
"codex-config",
|
||||
"codex-exec-server",
|
||||
@@ -12218,6 +12296,16 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.13.3"
|
||||
|
||||
@@ -36,6 +36,7 @@ members = [
|
||||
"hooks",
|
||||
"secrets",
|
||||
"exec",
|
||||
"file-system",
|
||||
"exec-server",
|
||||
"execpolicy",
|
||||
"execpolicy-legacy",
|
||||
@@ -46,6 +47,8 @@ members = [
|
||||
"login",
|
||||
"codex-mcp",
|
||||
"mcp-server",
|
||||
"memories/read",
|
||||
"memories/write",
|
||||
"model-provider-info",
|
||||
"models-manager",
|
||||
"network-proxy",
|
||||
@@ -140,6 +143,7 @@ codex-core-plugins = { path = "core-plugins" }
|
||||
codex-core-skills = { path = "core-skills" }
|
||||
codex-device-key = { path = "device-key" }
|
||||
codex-exec = { path = "exec" }
|
||||
codex-file-system = { path = "file-system" }
|
||||
codex-exec-server = { path = "exec-server" }
|
||||
codex-execpolicy = { path = "execpolicy" }
|
||||
codex-experimental-api-macros = { path = "codex-experimental-api-macros" }
|
||||
@@ -153,6 +157,8 @@ codex-keyring-store = { path = "keyring-store" }
|
||||
codex-linux-sandbox = { path = "linux-sandbox" }
|
||||
codex-lmstudio = { path = "lmstudio" }
|
||||
codex-login = { path = "login" }
|
||||
codex-memories-read = { path = "memories/read" }
|
||||
codex-memories-write = { path = "memories/write" }
|
||||
codex-mcp = { path = "codex-mcp" }
|
||||
codex-mcp-server = { path = "mcp-server" }
|
||||
codex-model-provider-info = { path = "model-provider-info" }
|
||||
@@ -254,6 +260,7 @@ encoding_rs = "0.8.35"
|
||||
env-flags = "0.1.1"
|
||||
env_logger = "0.11.9"
|
||||
eventsource-stream = "0.2.3"
|
||||
flate2 = "1.1.8"
|
||||
futures = { version = "0.3", default-features = false }
|
||||
gethostname = "1.1.0"
|
||||
gix = { version = "0.81.0", default-features = false, features = ["sha1"] }
|
||||
@@ -346,6 +353,7 @@ strum_macros = "0.28.0"
|
||||
supports-color = "3.0.2"
|
||||
syntect = "5"
|
||||
sys-locale = "0.3.2"
|
||||
tar = { version = "=0.4.45", default-features = false }
|
||||
tempfile = "3.23.0"
|
||||
test-log = "0.2.19"
|
||||
textwrap = "0.16.2"
|
||||
|
||||
@@ -94,7 +94,7 @@ In `workspace-write`, Codex also includes `~/.codex/memories` in its writable ro
|
||||
|
||||
This folder is the root of a Cargo workspace. It contains quite a bit of experimental code, but here are the key crates:
|
||||
|
||||
- [`core/`](./core) contains the business logic for Codex. Ultimately, we hope this to be a library crate that is generally useful for building other Rust/native applications that use Codex.
|
||||
- [`core/`](./core) contains the business logic for Codex. Ultimately, we hope this becomes a library crate that is generally useful for building other Rust/native applications that use Codex.
|
||||
- [`exec/`](./exec) "headless" CLI for use in automation.
|
||||
- [`tui/`](./tui) CLI that launches a fullscreen TUI built with [Ratatui](https://ratatui.rs/).
|
||||
- [`cli/`](./cli) CLI multitool that provides the aforementioned CLIs via subcommands.
|
||||
|
||||
@@ -19,6 +19,7 @@ chrono = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
crypto_box = { workspace = true }
|
||||
ed25519-dalek = { workspace = true }
|
||||
jsonwebtoken = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
@@ -8,6 +8,7 @@ use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
|
||||
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
|
||||
use chrono::SecondsFormat;
|
||||
use chrono::Utc;
|
||||
use codex_protocol::account::PlanType as AccountPlanType;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use crypto_box::SecretKey as Curve25519SecretKey;
|
||||
use ed25519_dalek::Signer as _;
|
||||
@@ -15,10 +16,14 @@ use ed25519_dalek::SigningKey;
|
||||
use ed25519_dalek::VerifyingKey;
|
||||
use ed25519_dalek::pkcs8::DecodePrivateKey;
|
||||
use ed25519_dalek::pkcs8::EncodePrivateKey;
|
||||
use jsonwebtoken::Algorithm;
|
||||
use jsonwebtoken::DecodingKey;
|
||||
use jsonwebtoken::Validation;
|
||||
use rand::TryRngCore;
|
||||
use rand::rngs::OsRng;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use sha2::Digest as _;
|
||||
use sha2::Sha512;
|
||||
|
||||
@@ -50,6 +55,18 @@ pub struct GeneratedAgentKeyMaterial {
|
||||
pub public_key_ssh: String,
|
||||
}
|
||||
|
||||
/// Claims carried by an Agent Identity JWT.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
|
||||
pub struct AgentIdentityJwtClaims {
|
||||
pub agent_runtime_id: String,
|
||||
pub agent_private_key: String,
|
||||
pub account_id: String,
|
||||
pub chatgpt_user_id: String,
|
||||
pub email: String,
|
||||
pub plan_type: AccountPlanType,
|
||||
pub chatgpt_account_is_fedramp: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
struct AgentAssertionEnvelope {
|
||||
agent_runtime_id: String,
|
||||
@@ -98,6 +115,43 @@ pub fn authorization_header_for_agent_task(
|
||||
Ok(format!("AgentAssertion {serialized_assertion}"))
|
||||
}
|
||||
|
||||
pub fn decode_agent_identity_jwt(
|
||||
jwt: &str,
|
||||
public_key_base64: Option<&str>,
|
||||
) -> Result<AgentIdentityJwtClaims> {
|
||||
let Some(public_key_base64) = public_key_base64 else {
|
||||
return decode_agent_identity_jwt_payload(jwt);
|
||||
};
|
||||
|
||||
let mut validation = Validation::new(Algorithm::EdDSA);
|
||||
validation.required_spec_claims.clear();
|
||||
validation.validate_exp = false;
|
||||
validation.validate_aud = false;
|
||||
|
||||
let public_key = BASE64_STANDARD
|
||||
.decode(public_key_base64)
|
||||
.context("agent identity JWT public key is not valid base64")?;
|
||||
let decoding_key = DecodingKey::from_ed_der(&public_key);
|
||||
|
||||
jsonwebtoken::decode::<AgentIdentityJwtClaims>(jwt, &decoding_key, &validation)
|
||||
.map(|data| data.claims)
|
||||
.context("failed to decode agent identity JWT")
|
||||
}
|
||||
|
||||
fn decode_agent_identity_jwt_payload<T: DeserializeOwned>(jwt: &str) -> Result<T> {
|
||||
let mut parts = jwt.split('.');
|
||||
let (_header_b64, payload_b64, _sig_b64) = match (parts.next(), parts.next(), parts.next()) {
|
||||
(Some(h), Some(p), Some(s)) if !h.is_empty() && !p.is_empty() && !s.is_empty() => (h, p, s),
|
||||
_ => anyhow::bail!("invalid agent identity JWT format"),
|
||||
};
|
||||
anyhow::ensure!(parts.next().is_none(), "invalid agent identity JWT format");
|
||||
|
||||
let payload_bytes = URL_SAFE_NO_PAD
|
||||
.decode(payload_b64)
|
||||
.context("agent identity JWT payload is not valid base64url")?;
|
||||
serde_json::from_slice(&payload_bytes).context("agent identity JWT payload is not valid JSON")
|
||||
}
|
||||
|
||||
pub fn sign_task_registration_payload(
|
||||
key: AgentIdentityKey<'_>,
|
||||
timestamp: &str,
|
||||
@@ -117,19 +171,27 @@ pub async fn register_agent_task(
|
||||
signature: sign_task_registration_payload(key, ×tamp)?,
|
||||
timestamp,
|
||||
};
|
||||
let url = agent_task_registration_url(chatgpt_base_url, key.agent_runtime_id);
|
||||
|
||||
let response = client
|
||||
.post(agent_task_registration_url(
|
||||
chatgpt_base_url,
|
||||
key.agent_runtime_id,
|
||||
))
|
||||
.post(url)
|
||||
.timeout(AGENT_TASK_REGISTRATION_TIMEOUT)
|
||||
.json(&request)
|
||||
.send()
|
||||
.await
|
||||
.context("failed to register agent task")?
|
||||
.error_for_status()
|
||||
.context("failed to register agent task")?
|
||||
.context("failed to register agent task")?;
|
||||
if !response.status().is_success() {
|
||||
let status = response.status();
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
let body = if body.len() > 512 {
|
||||
format!("{}...", body.chars().take(512).collect::<String>())
|
||||
} else {
|
||||
body
|
||||
};
|
||||
anyhow::bail!("failed to register agent task with status {status}: {body}");
|
||||
}
|
||||
|
||||
let response = response
|
||||
.json()
|
||||
.await
|
||||
.context("failed to decode agent task registration response")?;
|
||||
@@ -260,6 +322,7 @@ pub fn build_abom(session_source: SessionSource) -> AgentBillOfMaterials {
|
||||
| SessionSource::Exec
|
||||
| SessionSource::Mcp
|
||||
| SessionSource::Custom(_)
|
||||
| SessionSource::Internal(_)
|
||||
| SessionSource::SubAgent(_)
|
||||
| SessionSource::Unknown => "codex-cli".to_string(),
|
||||
},
|
||||
@@ -323,6 +386,8 @@ mod tests {
|
||||
use base64::Engine as _;
|
||||
use ed25519_dalek::Signature;
|
||||
use ed25519_dalek::Verifier as _;
|
||||
use jsonwebtoken::EncodingKey;
|
||||
use jsonwebtoken::Header;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
@@ -404,6 +469,119 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_agent_identity_jwt_reads_claims() {
|
||||
let jwt = jwt_with_payload(serde_json::json!({
|
||||
"agent_runtime_id": "agent-runtime-id",
|
||||
"agent_private_key": "private-key",
|
||||
"account_id": "account-id",
|
||||
"chatgpt_user_id": "user-id",
|
||||
"email": "user@example.com",
|
||||
"plan_type": "pro",
|
||||
"chatgpt_account_is_fedramp": false,
|
||||
}));
|
||||
|
||||
let claims =
|
||||
decode_agent_identity_jwt(&jwt, /*public_key_base64*/ None).expect("JWT should decode");
|
||||
|
||||
assert_eq!(
|
||||
claims,
|
||||
AgentIdentityJwtClaims {
|
||||
agent_runtime_id: "agent-runtime-id".to_string(),
|
||||
agent_private_key: "private-key".to_string(),
|
||||
account_id: "account-id".to_string(),
|
||||
chatgpt_user_id: "user-id".to_string(),
|
||||
email: "user@example.com".to_string(),
|
||||
plan_type: AccountPlanType::Pro,
|
||||
chatgpt_account_is_fedramp: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_agent_identity_jwt_verifies_when_public_key_is_present() {
|
||||
let mut secret_key_bytes = [0u8; 32];
|
||||
secret_key_bytes[0] = 1;
|
||||
let signing_key = SigningKey::from_bytes(&secret_key_bytes);
|
||||
let private_key_pkcs8 = signing_key
|
||||
.to_pkcs8_der()
|
||||
.expect("private key should encode");
|
||||
let public_key_base64 = BASE64_STANDARD.encode(signing_key.verifying_key().as_bytes());
|
||||
let claims = AgentIdentityJwtClaims {
|
||||
agent_runtime_id: "agent-runtime-id".to_string(),
|
||||
agent_private_key: "private-key".to_string(),
|
||||
account_id: "account-id".to_string(),
|
||||
chatgpt_user_id: "user-id".to_string(),
|
||||
email: "user@example.com".to_string(),
|
||||
plan_type: AccountPlanType::Pro,
|
||||
chatgpt_account_is_fedramp: false,
|
||||
};
|
||||
let jwt = jsonwebtoken::encode(
|
||||
&Header::new(Algorithm::EdDSA),
|
||||
&serde_json::json!({
|
||||
"agent_runtime_id": claims.agent_runtime_id,
|
||||
"agent_private_key": claims.agent_private_key,
|
||||
"account_id": claims.account_id,
|
||||
"chatgpt_user_id": claims.chatgpt_user_id,
|
||||
"email": claims.email,
|
||||
"plan_type": "pro",
|
||||
"chatgpt_account_is_fedramp": claims.chatgpt_account_is_fedramp,
|
||||
}),
|
||||
&EncodingKey::from_ed_der(private_key_pkcs8.as_bytes()),
|
||||
)
|
||||
.expect("JWT should encode");
|
||||
|
||||
let expected_claims = AgentIdentityJwtClaims {
|
||||
agent_runtime_id: "agent-runtime-id".to_string(),
|
||||
agent_private_key: "private-key".to_string(),
|
||||
account_id: "account-id".to_string(),
|
||||
chatgpt_user_id: "user-id".to_string(),
|
||||
email: "user@example.com".to_string(),
|
||||
plan_type: AccountPlanType::Pro,
|
||||
chatgpt_account_is_fedramp: false,
|
||||
};
|
||||
assert_eq!(
|
||||
decode_agent_identity_jwt(&jwt, Some(&public_key_base64)).expect("JWT should verify"),
|
||||
expected_claims
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_agent_identity_jwt_rejects_wrong_public_key() {
|
||||
let mut signing_secret_key_bytes = [0u8; 32];
|
||||
signing_secret_key_bytes[0] = 1;
|
||||
let signing_key = SigningKey::from_bytes(&signing_secret_key_bytes);
|
||||
let private_key_pkcs8 = signing_key
|
||||
.to_pkcs8_der()
|
||||
.expect("private key should encode");
|
||||
|
||||
let mut other_secret_key_bytes = [0u8; 32];
|
||||
other_secret_key_bytes[0] = 2;
|
||||
let other_public_key_base64 = BASE64_STANDARD.encode(
|
||||
SigningKey::from_bytes(&other_secret_key_bytes)
|
||||
.verifying_key()
|
||||
.as_bytes(),
|
||||
);
|
||||
|
||||
let jwt = jsonwebtoken::encode(
|
||||
&Header::new(Algorithm::EdDSA),
|
||||
&serde_json::json!({
|
||||
"agent_runtime_id": "agent-runtime-id",
|
||||
"agent_private_key": "private-key",
|
||||
"account_id": "account-id",
|
||||
"chatgpt_user_id": "user-id",
|
||||
"email": "user@example.com",
|
||||
"plan_type": "pro",
|
||||
"chatgpt_account_is_fedramp": false,
|
||||
}),
|
||||
&EncodingKey::from_ed_der(private_key_pkcs8.as_bytes()),
|
||||
)
|
||||
.expect("JWT should encode");
|
||||
|
||||
decode_agent_identity_jwt(&jwt, Some(&other_public_key_base64))
|
||||
.expect_err("JWT should not verify");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_chatgpt_base_url_strips_codex_before_backend_api() {
|
||||
assert_eq!(
|
||||
@@ -411,4 +589,12 @@ mod tests {
|
||||
"https://chatgpt.com/backend-api"
|
||||
);
|
||||
}
|
||||
|
||||
fn jwt_with_payload(payload: serde_json::Value) -> String {
|
||||
let encode = |bytes: &[u8]| URL_SAFE_NO_PAD.encode(bytes);
|
||||
let header_b64 = encode(br#"{"alg":"none","typ":"JWT"}"#);
|
||||
let payload_b64 = encode(&serde_json::to_vec(&payload).expect("payload should serialize"));
|
||||
let signature_b64 = encode(b"sig");
|
||||
format!("{header_b64}.{payload_b64}.{signature_b64}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ workspace = true
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-git-utils = { workspace = true }
|
||||
codex-login = { workspace = true }
|
||||
codex-model-provider = { workspace = true }
|
||||
codex-plugin = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
os_info = { workspace = true }
|
||||
|
||||
@@ -161,11 +161,7 @@ fn sample_thread_start_response(thread_id: &str, ephemeral: bool, model: &str) -
|
||||
}
|
||||
|
||||
fn sample_permission_profile() -> AppServerPermissionProfile {
|
||||
CorePermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::DangerFullAccess,
|
||||
&test_path_buf("/tmp"),
|
||||
)
|
||||
.into()
|
||||
CorePermissionProfile::Disabled.into()
|
||||
}
|
||||
|
||||
fn sample_app_server_client_metadata() -> CodexAppServerClientMetadata {
|
||||
@@ -319,7 +315,10 @@ fn sample_turn_resolved_config(turn_id: &str) -> TurnResolvedConfigFact {
|
||||
session_source: SessionSource::Exec,
|
||||
model: "gpt-5".to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: CorePermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_read_only_policy(),
|
||||
),
|
||||
permission_profile_cwd: PathBuf::from("/tmp"),
|
||||
reasoning_effort: None,
|
||||
reasoning_summary: None,
|
||||
service_tier: None,
|
||||
|
||||
@@ -312,16 +312,9 @@ async fn send_track_events(
|
||||
let Some(auth) = auth_manager.auth().await else {
|
||||
return;
|
||||
};
|
||||
if !auth.is_chatgpt_auth() {
|
||||
if !auth.uses_codex_backend() {
|
||||
return;
|
||||
}
|
||||
let access_token = match auth.get_token() {
|
||||
Ok(token) => token,
|
||||
Err(_) => return,
|
||||
};
|
||||
let Some(account_id) = auth.get_account_id() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let base_url = base_url.trim_end_matches('/');
|
||||
let url = format!("{base_url}/codex/analytics-events/events");
|
||||
@@ -330,8 +323,7 @@ async fn send_track_events(
|
||||
let response = create_client()
|
||||
.post(&url)
|
||||
.timeout(ANALYTICS_EVENTS_TIMEOUT)
|
||||
.bearer_auth(&access_token)
|
||||
.header("chatgpt-account-id", &account_id)
|
||||
.headers(codex_model_provider::auth_provider_from_auth(&auth).to_auth_headers())
|
||||
.header("Content-Type", "application/json")
|
||||
.json(&payload)
|
||||
.send()
|
||||
|
||||
@@ -23,7 +23,7 @@ use codex_app_server_protocol::CodexErrorInfo;
|
||||
use codex_login::default_client::originator;
|
||||
use codex_plugin::PluginTelemetryMetadata;
|
||||
use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::AdditionalPermissionProfile;
|
||||
use codex_protocol::models::SandboxPermissions;
|
||||
use codex_protocol::protocol::GuardianAssessmentOutcome;
|
||||
use codex_protocol::protocol::GuardianCommandSource;
|
||||
@@ -180,17 +180,17 @@ pub enum GuardianApprovalRequestSource {
|
||||
pub enum GuardianReviewedAction {
|
||||
Shell {
|
||||
sandbox_permissions: SandboxPermissions,
|
||||
additional_permissions: Option<PermissionProfile>,
|
||||
additional_permissions: Option<AdditionalPermissionProfile>,
|
||||
},
|
||||
UnifiedExec {
|
||||
sandbox_permissions: SandboxPermissions,
|
||||
additional_permissions: Option<PermissionProfile>,
|
||||
additional_permissions: Option<AdditionalPermissionProfile>,
|
||||
tty: bool,
|
||||
},
|
||||
Execve {
|
||||
source: GuardianCommandSource,
|
||||
program: String,
|
||||
additional_permissions: Option<PermissionProfile>,
|
||||
additional_permissions: Option<AdditionalPermissionProfile>,
|
||||
},
|
||||
ApplyPatch {},
|
||||
NetworkAccess {
|
||||
|
||||
@@ -13,12 +13,12 @@ use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::HookEventName;
|
||||
use codex_protocol::protocol::HookRunStatus;
|
||||
use codex_protocol::protocol::HookSource;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
@@ -62,7 +62,8 @@ pub struct TurnResolvedConfigFact {
|
||||
pub session_source: SessionSource,
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
pub sandbox_policy: SandboxPolicy,
|
||||
pub permission_profile: PermissionProfile,
|
||||
pub permission_profile_cwd: PathBuf,
|
||||
pub reasoning_effort: Option<ReasoningEffort>,
|
||||
pub reasoning_summary: Option<ReasoningSummary>,
|
||||
pub service_tier: Option<ServiceTier>,
|
||||
|
||||
@@ -61,7 +61,7 @@ use codex_login::default_client::originator;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
@@ -106,6 +106,7 @@ impl ThreadMetadataState {
|
||||
| SessionSource::Exec
|
||||
| SessionSource::Mcp
|
||||
| SessionSource::Custom(_)
|
||||
| SessionSource::Internal(_)
|
||||
| SessionSource::Unknown => (None, None),
|
||||
};
|
||||
Self {
|
||||
@@ -884,7 +885,8 @@ fn codex_turn_event_params(
|
||||
session_source: _session_source,
|
||||
model,
|
||||
model_provider,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
permission_profile_cwd,
|
||||
reasoning_effort,
|
||||
reasoning_summary,
|
||||
service_tier,
|
||||
@@ -909,7 +911,10 @@ fn codex_turn_event_params(
|
||||
parent_thread_id: thread_metadata.parent_thread_id.clone(),
|
||||
model: Some(model),
|
||||
model_provider,
|
||||
sandbox_policy: Some(sandbox_policy_mode(&sandbox_policy)),
|
||||
sandbox_policy: Some(sandbox_policy_mode(
|
||||
&permission_profile,
|
||||
permission_profile_cwd.as_path(),
|
||||
)),
|
||||
reasoning_effort: reasoning_effort.map(|value| value.to_string()),
|
||||
reasoning_summary: reasoning_summary_mode(reasoning_summary),
|
||||
service_tier: service_tier
|
||||
@@ -954,12 +959,27 @@ fn codex_turn_event_params(
|
||||
}
|
||||
}
|
||||
|
||||
fn sandbox_policy_mode(sandbox_policy: &SandboxPolicy) -> &'static str {
|
||||
match sandbox_policy {
|
||||
SandboxPolicy::DangerFullAccess => "full_access",
|
||||
SandboxPolicy::ReadOnly { .. } => "read_only",
|
||||
SandboxPolicy::WorkspaceWrite { .. } => "workspace_write",
|
||||
SandboxPolicy::ExternalSandbox { .. } => "external_sandbox",
|
||||
fn sandbox_policy_mode(permission_profile: &PermissionProfile, cwd: &Path) -> &'static str {
|
||||
match permission_profile {
|
||||
PermissionProfile::Disabled => "full_access",
|
||||
PermissionProfile::External { .. } => "external_sandbox",
|
||||
PermissionProfile::Managed { .. } => {
|
||||
let file_system_policy = permission_profile.file_system_sandbox_policy();
|
||||
if file_system_policy.has_full_disk_write_access() {
|
||||
if permission_profile.network_sandbox_policy().is_enabled() {
|
||||
"full_access"
|
||||
} else {
|
||||
"external_sandbox"
|
||||
}
|
||||
} else if file_system_policy
|
||||
.get_writable_roots_with_cwd(cwd)
|
||||
.is_empty()
|
||||
{
|
||||
"read_only"
|
||||
} else {
|
||||
"workspace_write"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1050,3 +1070,25 @@ pub(crate) fn normalize_path_for_skill_id(
|
||||
_ => resolved_path.to_string_lossy().replace('\\', "/"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codex_protocol::models::SandboxEnforcement;
|
||||
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
|
||||
#[test]
|
||||
fn managed_full_disk_with_restricted_network_reports_external_sandbox() {
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
SandboxEnforcement::Managed,
|
||||
&FileSystemSandboxPolicy::unrestricted(),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sandbox_policy_mode(&permission_profile, Path::new("/")),
|
||||
"external_sandbox"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ use codex_app_server_protocol::Result as JsonRpcResult;
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_app_server_protocol::ServerRequest;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_config::CloudRequirementsLoader;
|
||||
use codex_config::LoaderOverrides;
|
||||
use codex_config::NoopThreadConfigLoader;
|
||||
use codex_config::RemoteThreadConfigLoader;
|
||||
use codex_config::ThreadConfigLoader;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config_loader::CloudRequirementsLoader;
|
||||
use codex_core::config_loader::LoaderOverrides;
|
||||
pub use codex_exec_server::EnvironmentManager;
|
||||
pub use codex_exec_server::EnvironmentManagerArgs;
|
||||
pub use codex_exec_server::ExecServerRuntimePaths;
|
||||
@@ -1396,6 +1396,55 @@ mod tests {
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn remote_typed_request_accepts_large_single_frame_response() {
|
||||
let padding = "x".repeat((17 << 20) + 1024);
|
||||
let websocket_url = start_test_remote_server(move |mut websocket| async move {
|
||||
expect_remote_initialize(&mut websocket).await;
|
||||
let JSONRPCMessage::Request(request) = read_websocket_message(&mut websocket).await
|
||||
else {
|
||||
panic!("expected account/read request");
|
||||
};
|
||||
assert_eq!(request.method, "account/read");
|
||||
write_websocket_message(
|
||||
&mut websocket,
|
||||
JSONRPCMessage::Response(JSONRPCResponse {
|
||||
id: request.id,
|
||||
result: serde_json::json!({
|
||||
"account": null,
|
||||
"requiresOpenaiAuth": false,
|
||||
"padding": padding,
|
||||
}),
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
websocket.close(None).await.expect("close should succeed");
|
||||
})
|
||||
.await;
|
||||
let client = RemoteAppServerClient::connect(test_remote_connect_args(websocket_url))
|
||||
.await
|
||||
.expect("remote client should connect");
|
||||
|
||||
let response: GetAccountResponse = client
|
||||
.request_typed(ClientRequest::GetAccount {
|
||||
request_id: RequestId::Integer(1),
|
||||
params: codex_app_server_protocol::GetAccountParams {
|
||||
refresh_token: false,
|
||||
},
|
||||
})
|
||||
.await
|
||||
.expect("large typed request should succeed");
|
||||
assert_eq!(
|
||||
response,
|
||||
GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
}
|
||||
);
|
||||
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn remote_connect_includes_auth_header_when_configured() {
|
||||
let auth_token = "remote-bearer-token".to_string();
|
||||
|
||||
@@ -45,16 +45,18 @@ use tokio::sync::oneshot;
|
||||
use tokio::time::timeout;
|
||||
use tokio_tungstenite::MaybeTlsStream;
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
use tokio_tungstenite::connect_async;
|
||||
use tokio_tungstenite::connect_async_with_config;
|
||||
use tokio_tungstenite::tungstenite::Message;
|
||||
use tokio_tungstenite::tungstenite::client::IntoClientRequest;
|
||||
use tokio_tungstenite::tungstenite::http::HeaderValue;
|
||||
use tokio_tungstenite::tungstenite::http::header::AUTHORIZATION;
|
||||
use tokio_tungstenite::tungstenite::protocol::WebSocketConfig;
|
||||
use tracing::warn;
|
||||
use url::Url;
|
||||
|
||||
const CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const INITIALIZE_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const REMOTE_APP_SERVER_MAX_WEBSOCKET_MESSAGE_SIZE: usize = 128 << 20;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RemoteAppServerConnectArgs {
|
||||
@@ -170,20 +172,32 @@ impl RemoteAppServerClient {
|
||||
request.headers_mut().insert(AUTHORIZATION, header_value);
|
||||
}
|
||||
ensure_rustls_crypto_provider();
|
||||
let stream = timeout(CONNECT_TIMEOUT, connect_async(request))
|
||||
.await
|
||||
.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::TimedOut,
|
||||
format!("timed out connecting to remote app server at `{websocket_url}`"),
|
||||
)
|
||||
})?
|
||||
.map(|(stream, _response)| stream)
|
||||
.map_err(|err| {
|
||||
IoError::other(format!(
|
||||
"failed to connect to remote app server at `{websocket_url}`: {err}"
|
||||
))
|
||||
})?;
|
||||
// Remote resume responses can legitimately carry large thread histories.
|
||||
// Keep a bounded cap, but raise it above tungstenite's 16 MiB frame default.
|
||||
let websocket_config = WebSocketConfig::default()
|
||||
.max_frame_size(Some(REMOTE_APP_SERVER_MAX_WEBSOCKET_MESSAGE_SIZE))
|
||||
.max_message_size(Some(REMOTE_APP_SERVER_MAX_WEBSOCKET_MESSAGE_SIZE));
|
||||
let stream = timeout(
|
||||
CONNECT_TIMEOUT,
|
||||
connect_async_with_config(
|
||||
request,
|
||||
Some(websocket_config),
|
||||
/*disable_nagle*/ false,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::TimedOut,
|
||||
format!("timed out connecting to remote app server at `{websocket_url}`"),
|
||||
)
|
||||
})?
|
||||
.map(|(stream, _response)| stream)
|
||||
.map_err(|err| {
|
||||
IoError::other(format!(
|
||||
"failed to connect to remote app server at `{websocket_url}`: {err}"
|
||||
))
|
||||
})?;
|
||||
let mut stream = stream;
|
||||
let pending_events = initialize_remote_connection(
|
||||
&mut stream,
|
||||
@@ -198,6 +212,7 @@ impl RemoteAppServerClient {
|
||||
let worker_handle = tokio::spawn(async move {
|
||||
let mut pending_requests =
|
||||
HashMap::<RequestId, oneshot::Sender<IoResult<RequestResult>>>::new();
|
||||
let mut worker_exit_error: Option<(ErrorKind, String)> = None;
|
||||
loop {
|
||||
tokio::select! {
|
||||
command = command_rx.recv() => {
|
||||
@@ -224,17 +239,19 @@ impl RemoteAppServerClient {
|
||||
.await
|
||||
{
|
||||
let err_message = err.to_string();
|
||||
let message = format!(
|
||||
"remote app server at `{websocket_url}` write failed: {err_message}"
|
||||
);
|
||||
if let Some(response_tx) = pending_requests.remove(&request_id) {
|
||||
let _ = response_tx.send(Err(err));
|
||||
}
|
||||
let _ = deliver_event(
|
||||
&event_tx,
|
||||
AppServerEvent::Disconnected {
|
||||
message: format!(
|
||||
"remote app server at `{websocket_url}` write failed: {err_message}"
|
||||
),
|
||||
message: message.clone(),
|
||||
},
|
||||
);
|
||||
worker_exit_error = Some((ErrorKind::BrokenPipe, message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -351,28 +368,34 @@ impl RemoteAppServerClient {
|
||||
.await
|
||||
{
|
||||
let err_message = reject_err.to_string();
|
||||
let message = format!(
|
||||
"remote app server at `{websocket_url}` write failed: {err_message}"
|
||||
);
|
||||
let _ = deliver_event(
|
||||
&event_tx,
|
||||
AppServerEvent::Disconnected {
|
||||
message: format!(
|
||||
"remote app server at `{websocket_url}` write failed: {err_message}"
|
||||
),
|
||||
message: message.clone(),
|
||||
},
|
||||
);
|
||||
worker_exit_error =
|
||||
Some((ErrorKind::BrokenPipe, message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let message = format!(
|
||||
"remote app server at `{websocket_url}` sent invalid JSON-RPC: {err}"
|
||||
);
|
||||
let _ = deliver_event(
|
||||
&event_tx,
|
||||
AppServerEvent::Disconnected {
|
||||
message: format!(
|
||||
"remote app server at `{websocket_url}` sent invalid JSON-RPC: {err}"
|
||||
),
|
||||
message: message.clone(),
|
||||
},
|
||||
);
|
||||
worker_exit_error =
|
||||
Some((ErrorKind::InvalidData, message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -383,14 +406,19 @@ impl RemoteAppServerClient {
|
||||
.map(|frame| frame.reason.to_string())
|
||||
.filter(|reason| !reason.is_empty())
|
||||
.unwrap_or_else(|| "connection closed".to_string());
|
||||
let message = format!(
|
||||
"remote app server at `{websocket_url}` disconnected: {reason}"
|
||||
);
|
||||
let _ = deliver_event(
|
||||
&event_tx,
|
||||
AppServerEvent::Disconnected {
|
||||
message: format!(
|
||||
"remote app server at `{websocket_url}` disconnected: {reason}"
|
||||
),
|
||||
message: message.clone(),
|
||||
},
|
||||
);
|
||||
worker_exit_error = Some((
|
||||
ErrorKind::ConnectionAborted,
|
||||
message,
|
||||
));
|
||||
break;
|
||||
}
|
||||
Some(Ok(Message::Binary(_)))
|
||||
@@ -398,25 +426,29 @@ impl RemoteAppServerClient {
|
||||
| Some(Ok(Message::Pong(_)))
|
||||
| Some(Ok(Message::Frame(_))) => {}
|
||||
Some(Err(err)) => {
|
||||
let message = format!(
|
||||
"remote app server at `{websocket_url}` transport failed: {err}"
|
||||
);
|
||||
let _ = deliver_event(
|
||||
&event_tx,
|
||||
AppServerEvent::Disconnected {
|
||||
message: format!(
|
||||
"remote app server at `{websocket_url}` transport failed: {err}"
|
||||
),
|
||||
message: message.clone(),
|
||||
},
|
||||
);
|
||||
worker_exit_error = Some((ErrorKind::InvalidData, message));
|
||||
break;
|
||||
}
|
||||
None => {
|
||||
let message = format!(
|
||||
"remote app server at `{websocket_url}` closed the connection"
|
||||
);
|
||||
let _ = deliver_event(
|
||||
&event_tx,
|
||||
AppServerEvent::Disconnected {
|
||||
message: format!(
|
||||
"remote app server at `{websocket_url}` closed the connection"
|
||||
),
|
||||
message: message.clone(),
|
||||
},
|
||||
);
|
||||
worker_exit_error = Some((ErrorKind::UnexpectedEof, message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -424,12 +456,14 @@ impl RemoteAppServerClient {
|
||||
}
|
||||
}
|
||||
|
||||
let err = IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"remote app-server worker channel is closed",
|
||||
);
|
||||
let (err_kind, err_message) = worker_exit_error.unwrap_or_else(|| {
|
||||
(
|
||||
ErrorKind::BrokenPipe,
|
||||
"remote app-server worker channel is closed".to_string(),
|
||||
)
|
||||
});
|
||||
for (_, response_tx) in pending_requests {
|
||||
let _ = response_tx.send(Err(IoError::new(err.kind(), err.to_string())));
|
||||
let _ = response_tx.send(Err(IoError::new(err_kind, err_message.clone())));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -218,17 +218,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional full permissions profile for this command.\n\nDefaults to the user's configured permissions when omitted. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"processId": {
|
||||
"description": "Optional client-supplied, connection-scoped process id.\n\nRequired for `tty`, `streamStdin`, `streamStdoutStderr`, and follow-up `command/exec/write`, `command/exec/resize`, and `command/exec/terminate` calls. When omitted, buffered execution gets an internal id that is not exposed to the client.",
|
||||
"type": [
|
||||
@@ -1028,21 +1017,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -1415,38 +1389,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"GhostCommit": {
|
||||
"description": "Details of a ghost commit created from a repository state.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preexisting_untracked_dirs": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"preexisting_untracked_files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"preexisting_untracked_dirs",
|
||||
"preexisting_untracked_files"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ImageDetail": {
|
||||
"enum": [
|
||||
"auto",
|
||||
@@ -1892,61 +1834,132 @@
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Personality": {
|
||||
@@ -2055,53 +2068,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RealtimeOutputModality": {
|
||||
"enum": [
|
||||
"text",
|
||||
@@ -2268,12 +2234,6 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"end_turn": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -2673,26 +2633,6 @@
|
||||
"title": "ImageGenerationCallResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"ghost_commit": {
|
||||
"$ref": "#/definitions/GhostCommit"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ghost_snapshot"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ghost_commit",
|
||||
"type"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"encrypted_content": {
|
||||
@@ -2985,16 +2925,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -3051,16 +2981,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -3340,17 +3260,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the forked thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"sandbox": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -3387,6 +3296,15 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalStatus": {
|
||||
"enum": [
|
||||
"active",
|
||||
"paused",
|
||||
"budgetLimited",
|
||||
"complete"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadInjectItemsParams": {
|
||||
"properties": {
|
||||
"items": {
|
||||
@@ -3747,17 +3665,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the resumed thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -3941,17 +3848,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for this thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -4163,17 +4059,6 @@
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the full permissions profile for this turn and subsequent turns. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -78,7 +78,8 @@
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
],
|
||||
"description": "Partial overlay used for per-command permission requests."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -391,21 +392,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
|
||||
@@ -177,21 +177,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
|
||||
@@ -177,21 +177,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
|
||||
@@ -1199,21 +1199,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -3028,6 +3013,93 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoal": {
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"objective": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/ThreadGoalStatus"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeUsedSeconds": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"tokenBudget": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tokensUsed": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"createdAt",
|
||||
"objective",
|
||||
"status",
|
||||
"threadId",
|
||||
"timeUsedSeconds",
|
||||
"tokensUsed",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalClearedNotification": {
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalStatus": {
|
||||
"enum": [
|
||||
"active",
|
||||
"paused",
|
||||
"budgetLimited",
|
||||
"complete"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadGoalUpdatedNotification": {
|
||||
"properties": {
|
||||
"goal": {
|
||||
"$ref": "#/definitions/ThreadGoal"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"goal",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadId": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -4727,6 +4799,46 @@
|
||||
"title": "Thread/name/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/goal/updated"
|
||||
],
|
||||
"title": "Thread/goal/updatedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadGoalUpdatedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/goal/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/goal/cleared"
|
||||
],
|
||||
"title": "Thread/goal/clearedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadGoalClearedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/goal/clearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
|
||||
@@ -78,7 +78,8 @@
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
],
|
||||
"description": "Partial overlay used for per-command permission requests."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -730,21 +731,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
],
|
||||
"description": "Partial overlay used for per-command permission requests."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -3805,6 +3806,46 @@
|
||||
"title": "Thread/name/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/goal/updated"
|
||||
],
|
||||
"title": "Thread/goal/updatedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadGoalUpdatedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/goal/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/goal/cleared"
|
||||
],
|
||||
"title": "Thread/goal/clearedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadGoalClearedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/goal/clearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -5220,6 +5261,22 @@
|
||||
],
|
||||
"title": "ChatgptAccount",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockAccountType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockAccount",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -6479,17 +6536,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional full permissions profile for this command.\n\nDefaults to the user's configured permissions when omitted. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"processId": {
|
||||
"description": "Optional client-supplied, connection-scoped process id.\n\nRequired for `tty`, `streamStdin`, `streamStdoutStderr`, and follow-up `command/exec/write`, `command/exec/resize`, and `command/exec/terminate` calls. When omitted, buffered execution gets an internal id that is not exposed to the client.",
|
||||
"type": [
|
||||
@@ -8516,21 +8562,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -9141,38 +9172,6 @@
|
||||
"title": "GetAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"GhostCommit": {
|
||||
"description": "Details of a ghost commit created from a repository state.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preexisting_untracked_dirs": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"preexisting_untracked_files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"preexisting_untracked_dirs",
|
||||
"preexisting_untracked_files"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"GitInfo": {
|
||||
"properties": {
|
||||
"branch": {
|
||||
@@ -11269,61 +11268,132 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/v2/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/v2/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/v2/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Personality": {
|
||||
@@ -12140,53 +12210,6 @@
|
||||
"title": "RawResponseItemCompletedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RealtimeConversationVersion": {
|
||||
"enum": [
|
||||
"v1",
|
||||
@@ -12658,12 +12681,6 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"end_turn": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -13063,26 +13080,6 @@
|
||||
"title": "ImageGenerationCallResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"ghost_commit": {
|
||||
"$ref": "#/definitions/v2/GhostCommit"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ghost_snapshot"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ghost_commit",
|
||||
"type"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"encrypted_content": {
|
||||
@@ -13395,16 +13392,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -13461,16 +13448,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -14455,17 +14432,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the forked thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"sandbox": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -14534,18 +14500,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -14590,6 +14544,97 @@
|
||||
"title": "ThreadForkResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoal": {
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"objective": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/v2/ThreadGoalStatus"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeUsedSeconds": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"tokenBudget": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tokensUsed": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"createdAt",
|
||||
"objective",
|
||||
"status",
|
||||
"threadId",
|
||||
"timeUsedSeconds",
|
||||
"tokensUsed",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalClearedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadGoalClearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalStatus": {
|
||||
"enum": [
|
||||
"active",
|
||||
"paused",
|
||||
"budgetLimited",
|
||||
"complete"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadGoalUpdatedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"goal": {
|
||||
"$ref": "#/definitions/v2/ThreadGoal"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"goal",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadGoalUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadId": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -15888,17 +15933,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the resumed thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -15977,18 +16011,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -16205,17 +16227,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for this thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -16304,18 +16315,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -17021,17 +17020,6 @@
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the full permissions profile for this turn and subsequent turns. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -46,6 +46,22 @@
|
||||
],
|
||||
"title": "ChatgptAccount",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockAccountType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockAccount",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3039,17 +3055,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional full permissions profile for this command.\n\nDefaults to the user's configured permissions when omitted. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"processId": {
|
||||
"description": "Optional client-supplied, connection-scoped process id.\n\nRequired for `tty`, `streamStdin`, `streamStdoutStderr`, and follow-up `command/exec/write`, `command/exec/resize`, and `command/exec/terminate` calls. When omitted, buffered execution gets an internal id that is not exposed to the client.",
|
||||
"type": [
|
||||
@@ -5076,21 +5081,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -5812,38 +5802,6 @@
|
||||
"title": "GetAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"GhostCommit": {
|
||||
"description": "Details of a ghost commit created from a repository state.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preexisting_untracked_dirs": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"preexisting_untracked_files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"preexisting_untracked_dirs",
|
||||
"preexisting_untracked_files"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"GitInfo": {
|
||||
"properties": {
|
||||
"branch": {
|
||||
@@ -7984,61 +7942,132 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Personality": {
|
||||
@@ -8855,53 +8884,6 @@
|
||||
"title": "RawResponseItemCompletedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RealtimeConversationVersion": {
|
||||
"enum": [
|
||||
"v1",
|
||||
@@ -9373,12 +9355,6 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"end_turn": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -9778,26 +9754,6 @@
|
||||
"title": "ImageGenerationCallResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"ghost_commit": {
|
||||
"$ref": "#/definitions/GhostCommit"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ghost_snapshot"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ghost_commit",
|
||||
"type"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"encrypted_content": {
|
||||
@@ -10110,16 +10066,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -10176,16 +10122,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -10424,6 +10360,46 @@
|
||||
"title": "Thread/name/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/goal/updated"
|
||||
],
|
||||
"title": "Thread/goal/updatedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadGoalUpdatedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/goal/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/goal/cleared"
|
||||
],
|
||||
"title": "Thread/goal/clearedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadGoalClearedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/goal/clearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -12342,17 +12318,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the forked thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"sandbox": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -12421,18 +12386,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -12477,6 +12430,97 @@
|
||||
"title": "ThreadForkResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoal": {
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"objective": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/ThreadGoalStatus"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeUsedSeconds": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"tokenBudget": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tokensUsed": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"createdAt",
|
||||
"objective",
|
||||
"status",
|
||||
"threadId",
|
||||
"timeUsedSeconds",
|
||||
"tokensUsed",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalClearedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadGoalClearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalStatus": {
|
||||
"enum": [
|
||||
"active",
|
||||
"paused",
|
||||
"budgetLimited",
|
||||
"complete"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadGoalUpdatedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"goal": {
|
||||
"$ref": "#/definitions/ThreadGoal"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"goal",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadGoalUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadId": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -13775,17 +13819,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the resumed thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -13864,18 +13897,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -14092,17 +14113,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for this thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -14191,18 +14201,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -14908,17 +14906,6 @@
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the full permissions profile for this turn and subsequent turns. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -146,21 +146,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -246,110 +231,134 @@
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -370,16 +379,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -436,16 +435,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -516,17 +505,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional full permissions profile for this command.\n\nDefaults to the user's configured permissions when omitted. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"processId": {
|
||||
"description": "Optional client-supplied, connection-scoped process id.\n\nRequired for `tty`, `streamStdin`, `streamStdoutStderr`, and follow-up `command/exec/write`, `command/exec/resize`, and `command/exec/terminate` calls. When omitted, buffered execution gets an internal id that is not exposed to the client.",
|
||||
"type": [
|
||||
|
||||
@@ -42,6 +42,22 @@
|
||||
],
|
||||
"title": "ChatgptAccount",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockAccountType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockAccount",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -184,21 +184,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
|
||||
@@ -177,21 +177,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
|
||||
@@ -143,38 +143,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"GhostCommit": {
|
||||
"description": "Details of a ghost commit created from a repository state.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preexisting_untracked_dirs": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"preexisting_untracked_files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"preexisting_untracked_dirs",
|
||||
"preexisting_untracked_files"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ImageDetail": {
|
||||
"enum": [
|
||||
"auto",
|
||||
@@ -345,12 +313,6 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"end_turn": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -750,26 +712,6 @@
|
||||
"title": "ImageGenerationCallResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"ghost_commit": {
|
||||
"$ref": "#/definitions/GhostCommit"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ghost_snapshot"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ghost_commit",
|
||||
"type"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"encrypted_content": {
|
||||
|
||||
@@ -183,21 +183,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -276,61 +261,132 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SandboxMode": {
|
||||
@@ -417,17 +473,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the forked thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"sandbox": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -569,21 +569,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -900,110 +885,134 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
@@ -1036,16 +1045,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -1102,16 +1101,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -2496,18 +2485,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
13
codex-rs/app-server-protocol/schema/json/v2/ThreadGoalClearedNotification.json
generated
Normal file
13
codex-rs/app-server-protocol/schema/json/v2/ThreadGoalClearedNotification.json
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadGoalClearedNotification",
|
||||
"type": "object"
|
||||
}
|
||||
80
codex-rs/app-server-protocol/schema/json/v2/ThreadGoalUpdatedNotification.json
generated
Normal file
80
codex-rs/app-server-protocol/schema/json/v2/ThreadGoalUpdatedNotification.json
generated
Normal file
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"ThreadGoal": {
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"objective": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/ThreadGoalStatus"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeUsedSeconds": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"tokenBudget": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tokensUsed": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"createdAt",
|
||||
"objective",
|
||||
"status",
|
||||
"threadId",
|
||||
"timeUsedSeconds",
|
||||
"tokensUsed",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadGoalStatus": {
|
||||
"enum": [
|
||||
"active",
|
||||
"paused",
|
||||
"budgetLimited",
|
||||
"complete"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"goal": {
|
||||
"$ref": "#/definitions/ThreadGoal"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"goal",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadGoalUpdatedNotification",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -257,21 +257,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -417,38 +402,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"GhostCommit": {
|
||||
"description": "Details of a ghost commit created from a repository state.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preexisting_untracked_dirs": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"preexisting_untracked_files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"preexisting_untracked_dirs",
|
||||
"preexisting_untracked_files"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ImageDetail": {
|
||||
"enum": [
|
||||
"auto",
|
||||
@@ -542,61 +495,132 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Personality": {
|
||||
@@ -685,12 +709,6 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"end_turn": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -1090,26 +1108,6 @@
|
||||
"title": "ImageGenerationCallResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"ghost_commit": {
|
||||
"$ref": "#/definitions/GhostCommit"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ghost_snapshot"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ghost_commit",
|
||||
"type"
|
||||
],
|
||||
"title": "GhostSnapshotResponseItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"encrypted_content": {
|
||||
@@ -1330,17 +1328,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for the resumed thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -569,21 +569,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -900,110 +885,134 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
@@ -1036,16 +1045,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -1102,16 +1101,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -2496,18 +2485,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -209,21 +209,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -302,61 +287,132 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Personality": {
|
||||
@@ -388,6 +444,21 @@
|
||||
"clear"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
@@ -455,17 +526,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Full permissions override for this thread. Cannot be combined with `sandbox`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -569,21 +569,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -900,110 +885,134 @@
|
||||
]
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
@@ -1036,16 +1045,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -1102,16 +1101,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -2496,18 +2485,6 @@
|
||||
"modelProvider": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||
},
|
||||
"reasoningEffort": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -218,21 +218,6 @@
|
||||
"title": "MinimalFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"current_working_directory"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"kind": {
|
||||
@@ -326,61 +311,132 @@
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Codex owns sandbox construction for this profile.",
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
"type": {
|
||||
"enum": [
|
||||
"managed"
|
||||
],
|
||||
"title": "ManagedPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"fileSystem",
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ManagedPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Do not apply an outer sandbox.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"disabled"
|
||||
],
|
||||
"title": "DisabledPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DisabledPermissionProfile",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Filesystem isolation is enforced by an external caller.",
|
||||
"properties": {
|
||||
"network": {
|
||||
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"external"
|
||||
],
|
||||
"title": "ExternalPermissionProfileType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"network",
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalPermissionProfile",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileFileSystemPermissions": {
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
"required": [
|
||||
"entries",
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
},
|
||||
"globScanMaxDepth": {
|
||||
"format": "uint",
|
||||
"minimum": 1.0,
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unrestricted"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissionsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnrestrictedPermissionProfileFileSystemPermissions",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entries"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"PermissionProfileNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Personality": {
|
||||
@@ -391,53 +447,6 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"includePlatformDefaults": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadOnlyAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullAccess"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullAccessReadOnlyAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
@@ -490,16 +499,6 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
@@ -556,16 +555,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReadOnlyAccess"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "fullAccess"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -840,17 +829,6 @@
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"permissionProfile": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the full permissions profile for this turn and subsequent turns. Cannot be combined with `sandboxPolicy`."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Details of a ghost commit created from a repository state.
|
||||
*/
|
||||
export type GhostCommit = { id: string, parent: string | null, preexisting_untracked_files: Array<string>, preexisting_untracked_dirs: Array<string>, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/InternalSessionSource.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/InternalSessionSource.ts
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type InternalSessionSource = "memory_consolidation";
|
||||
@@ -3,7 +3,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ContentItem } from "./ContentItem";
|
||||
import type { FunctionCallOutputBody } from "./FunctionCallOutputBody";
|
||||
import type { GhostCommit } from "./GhostCommit";
|
||||
import type { LocalShellAction } from "./LocalShellAction";
|
||||
import type { LocalShellStatus } from "./LocalShellStatus";
|
||||
import type { MessagePhase } from "./MessagePhase";
|
||||
@@ -11,8 +10,8 @@ import type { ReasoningItemContent } from "./ReasoningItemContent";
|
||||
import type { ReasoningItemReasoningSummary } from "./ReasoningItemReasoningSummary";
|
||||
import type { WebSearchAction } from "./WebSearchAction";
|
||||
|
||||
export type ResponseItem = { "type": "message", role: string, content: Array<ContentItem>, end_turn?: boolean, phase?: MessagePhase, } | { "type": "reasoning", summary: Array<ReasoningItemReasoningSummary>, content?: Array<ReasoningItemContent>, encrypted_content: string | null, } | { "type": "local_shell_call",
|
||||
export type ResponseItem = { "type": "message", role: string, content: Array<ContentItem>, phase?: MessagePhase, } | { "type": "reasoning", summary: Array<ReasoningItemReasoningSummary>, content?: Array<ReasoningItemContent>, encrypted_content: string | null, } | { "type": "local_shell_call",
|
||||
/**
|
||||
* Set when using the Responses API.
|
||||
*/
|
||||
call_id: string | null, status: LocalShellStatus, action: LocalShellAction, } | { "type": "function_call", name: string, namespace?: string, arguments: string, call_id: string, } | { "type": "tool_search_call", call_id: string | null, status?: string, execution: string, arguments: unknown, } | { "type": "function_call_output", call_id: string, output: FunctionCallOutputBody, } | { "type": "custom_tool_call", status?: string, call_id: string, name: string, input: string, } | { "type": "custom_tool_call_output", call_id: string, name?: string, output: FunctionCallOutputBody, } | { "type": "tool_search_output", call_id: string | null, status: string, execution: string, tools: unknown[], } | { "type": "web_search_call", status?: string, action?: WebSearchAction, } | { "type": "image_generation_call", id: string, status: string, revised_prompt?: string, result: string, } | { "type": "ghost_snapshot", ghost_commit: GhostCommit, } | { "type": "compaction", encrypted_content: string, } | { "type": "other" };
|
||||
call_id: string | null, status: LocalShellStatus, action: LocalShellAction, } | { "type": "function_call", name: string, namespace?: string, arguments: string, call_id: string, } | { "type": "tool_search_call", call_id: string | null, status?: string, execution: string, arguments: unknown, } | { "type": "function_call_output", call_id: string, output: FunctionCallOutputBody, } | { "type": "custom_tool_call", status?: string, call_id: string, name: string, input: string, } | { "type": "custom_tool_call_output", call_id: string, name?: string, output: FunctionCallOutputBody, } | { "type": "tool_search_output", call_id: string | null, status: string, execution: string, tools: unknown[], } | { "type": "web_search_call", status?: string, action?: WebSearchAction, } | { "type": "image_generation_call", id: string, status: string, revised_prompt?: string, result: string, } | { "type": "compaction", encrypted_content: string, } | { "type": "other" };
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { InternalSessionSource } from "./InternalSessionSource";
|
||||
import type { SubAgentSource } from "./SubAgentSource";
|
||||
|
||||
export type SessionSource = "cli" | "vscode" | "exec" | "mcp" | { "custom": string } | { "subagent": SubAgentSource } | "unknown";
|
||||
export type SessionSource = "cli" | "vscode" | "exec" | "mcp" | { "custom": string } | { "internal": InternalSessionSource } | { "subagent": SubAgentSource } | "unknown";
|
||||
|
||||
@@ -29,7 +29,6 @@ export type { GetAuthStatusParams } from "./GetAuthStatusParams";
|
||||
export type { GetAuthStatusResponse } from "./GetAuthStatusResponse";
|
||||
export type { GetConversationSummaryParams } from "./GetConversationSummaryParams";
|
||||
export type { GetConversationSummaryResponse } from "./GetConversationSummaryResponse";
|
||||
export type { GhostCommit } from "./GhostCommit";
|
||||
export type { GitDiffToRemoteParams } from "./GitDiffToRemoteParams";
|
||||
export type { GitDiffToRemoteResponse } from "./GitDiffToRemoteResponse";
|
||||
export type { GitSha } from "./GitSha";
|
||||
@@ -38,6 +37,7 @@ export type { InitializeCapabilities } from "./InitializeCapabilities";
|
||||
export type { InitializeParams } from "./InitializeParams";
|
||||
export type { InitializeResponse } from "./InitializeResponse";
|
||||
export type { InputModality } from "./InputModality";
|
||||
export type { InternalSessionSource } from "./InternalSessionSource";
|
||||
export type { LocalShellAction } from "./LocalShellAction";
|
||||
export type { LocalShellExecAction } from "./LocalShellExecAction";
|
||||
export type { LocalShellStatus } from "./LocalShellStatus";
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { PlanType } from "../PlanType";
|
||||
|
||||
export type Account = { "type": "apiKey", } | { "type": "chatgpt", email: string, planType: PlanType, };
|
||||
export type Account = { "type": "apiKey", } | { "type": "chatgpt", email: string, planType: PlanType, } | { "type": "amazonBedrock", };
|
||||
|
||||
@@ -4,4 +4,8 @@
|
||||
import type { AdditionalFileSystemPermissions } from "./AdditionalFileSystemPermissions";
|
||||
import type { AdditionalNetworkPermissions } from "./AdditionalNetworkPermissions";
|
||||
|
||||
export type AdditionalPermissionProfile = { network: AdditionalNetworkPermissions | null, fileSystem: AdditionalFileSystemPermissions | null, };
|
||||
export type AdditionalPermissionProfile = {
|
||||
/**
|
||||
* Partial overlay used for per-command permission requests.
|
||||
*/
|
||||
network: AdditionalNetworkPermissions | null, fileSystem: AdditionalFileSystemPermissions | null, };
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { CommandExecTerminalSize } from "./CommandExecTerminalSize";
|
||||
import type { PermissionProfile } from "./PermissionProfile";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
|
||||
/**
|
||||
@@ -13,12 +12,10 @@ import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
* sent only after all `command/exec/outputDelta` notifications for that
|
||||
* connection have been emitted.
|
||||
*/
|
||||
export type CommandExecParams = {
|
||||
/**
|
||||
export type CommandExecParams = {/**
|
||||
* Command argv vector. Empty arrays are rejected.
|
||||
*/
|
||||
command: Array<string>,
|
||||
/**
|
||||
command: Array<string>, /**
|
||||
* Optional client-supplied, connection-scoped process id.
|
||||
*
|
||||
* Required for `tty`, `streamStdin`, `streamStdoutStderr`, and follow-up
|
||||
@@ -26,81 +23,63 @@ command: Array<string>,
|
||||
* `command/exec/terminate` calls. When omitted, buffered execution gets an
|
||||
* internal id that is not exposed to the client.
|
||||
*/
|
||||
processId?: string | null,
|
||||
/**
|
||||
processId?: string | null, /**
|
||||
* Enable PTY mode.
|
||||
*
|
||||
* This implies `streamStdin` and `streamStdoutStderr`.
|
||||
*/
|
||||
tty?: boolean,
|
||||
/**
|
||||
tty?: boolean, /**
|
||||
* Allow follow-up `command/exec/write` requests to write stdin bytes.
|
||||
*
|
||||
* Requires a client-supplied `processId`.
|
||||
*/
|
||||
streamStdin?: boolean,
|
||||
/**
|
||||
streamStdin?: boolean, /**
|
||||
* Stream stdout/stderr via `command/exec/outputDelta` notifications.
|
||||
*
|
||||
* Streamed bytes are not duplicated into the final response and require a
|
||||
* client-supplied `processId`.
|
||||
*/
|
||||
streamStdoutStderr?: boolean,
|
||||
/**
|
||||
streamStdoutStderr?: boolean, /**
|
||||
* Optional per-stream stdout/stderr capture cap in bytes.
|
||||
*
|
||||
* When omitted, the server default applies. Cannot be combined with
|
||||
* `disableOutputCap`.
|
||||
*/
|
||||
outputBytesCap?: number | null,
|
||||
/**
|
||||
outputBytesCap?: number | null, /**
|
||||
* Disable stdout/stderr capture truncation for this request.
|
||||
*
|
||||
* Cannot be combined with `outputBytesCap`.
|
||||
*/
|
||||
disableOutputCap?: boolean,
|
||||
/**
|
||||
disableOutputCap?: boolean, /**
|
||||
* Disable the timeout entirely for this request.
|
||||
*
|
||||
* Cannot be combined with `timeoutMs`.
|
||||
*/
|
||||
disableTimeout?: boolean,
|
||||
/**
|
||||
disableTimeout?: boolean, /**
|
||||
* Optional timeout in milliseconds.
|
||||
*
|
||||
* When omitted, the server default applies. Cannot be combined with
|
||||
* `disableTimeout`.
|
||||
*/
|
||||
timeoutMs?: number | null,
|
||||
/**
|
||||
timeoutMs?: number | null, /**
|
||||
* Optional working directory. Defaults to the server cwd.
|
||||
*/
|
||||
cwd?: string | null,
|
||||
/**
|
||||
cwd?: string | null, /**
|
||||
* Optional environment overrides merged into the server-computed
|
||||
* environment.
|
||||
*
|
||||
* Matching names override inherited values. Set a key to `null` to unset
|
||||
* an inherited variable.
|
||||
*/
|
||||
env?: { [key in string]?: string | null } | null,
|
||||
/**
|
||||
env?: { [key in string]?: string | null } | null, /**
|
||||
* Optional initial PTY size in character cells. Only valid when `tty` is
|
||||
* true.
|
||||
*/
|
||||
size?: CommandExecTerminalSize | null,
|
||||
/**
|
||||
size?: CommandExecTerminalSize | null, /**
|
||||
* Optional sandbox policy for this command.
|
||||
*
|
||||
* Uses the same shape as thread/turn execution sandbox configuration and
|
||||
* defaults to the user's configured policy when omitted. Cannot be
|
||||
* combined with `permissionProfile`.
|
||||
*/
|
||||
sandboxPolicy?: SandboxPolicy | null,
|
||||
/**
|
||||
* Optional full permissions profile for this command.
|
||||
*
|
||||
* Defaults to the user's configured permissions when omitted. Cannot be
|
||||
* combined with `sandboxPolicy`.
|
||||
*/
|
||||
permissionProfile?: PermissionProfile | null, };
|
||||
sandboxPolicy?: SandboxPolicy | null};
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { AdditionalPermissionProfile } from "./AdditionalPermissionProfile";
|
||||
import type { CommandAction } from "./CommandAction";
|
||||
import type { CommandExecutionApprovalDecision } from "./CommandExecutionApprovalDecision";
|
||||
import type { ExecPolicyAmendment } from "./ExecPolicyAmendment";
|
||||
import type { NetworkApprovalContext } from "./NetworkApprovalContext";
|
||||
import type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment";
|
||||
|
||||
export type CommandExecutionRequestApprovalParams = { threadId: string, turnId: string, itemId: string,
|
||||
/**
|
||||
export type CommandExecutionRequestApprovalParams = {threadId: string, turnId: string, itemId: string, /**
|
||||
* Unique identifier for this specific approval callback.
|
||||
*
|
||||
* For regular shell/unified_exec approvals, this is null.
|
||||
@@ -19,40 +16,25 @@ export type CommandExecutionRequestApprovalParams = { threadId: string, turnId:
|
||||
* one parent `itemId`, so `approvalId` is a distinct opaque callback id
|
||||
* (a UUID) used to disambiguate routing.
|
||||
*/
|
||||
approvalId?: string | null,
|
||||
/**
|
||||
approvalId?: string | null, /**
|
||||
* Optional explanatory reason (e.g. request for network access).
|
||||
*/
|
||||
reason?: string | null,
|
||||
/**
|
||||
reason?: string | null, /**
|
||||
* Optional context for a managed-network approval prompt.
|
||||
*/
|
||||
networkApprovalContext?: NetworkApprovalContext | null,
|
||||
/**
|
||||
networkApprovalContext?: NetworkApprovalContext | null, /**
|
||||
* The command to be executed.
|
||||
*/
|
||||
command?: string | null,
|
||||
/**
|
||||
command?: string | null, /**
|
||||
* The command's working directory.
|
||||
*/
|
||||
cwd?: AbsolutePathBuf | null,
|
||||
/**
|
||||
cwd?: AbsolutePathBuf | null, /**
|
||||
* Best-effort parsed command actions for friendly display.
|
||||
*/
|
||||
commandActions?: Array<CommandAction> | null,
|
||||
/**
|
||||
* Optional additional permissions requested for this command.
|
||||
*/
|
||||
additionalPermissions?: AdditionalPermissionProfile | null,
|
||||
/**
|
||||
commandActions?: Array<CommandAction> | null, /**
|
||||
* Optional proposed execpolicy amendment to allow similar commands without prompting.
|
||||
*/
|
||||
proposedExecpolicyAmendment?: ExecPolicyAmendment | null,
|
||||
/**
|
||||
proposedExecpolicyAmendment?: ExecPolicyAmendment | null, /**
|
||||
* Optional proposed network policy amendments (allow/deny host) for future requests.
|
||||
*/
|
||||
proposedNetworkPolicyAmendments?: Array<NetworkPolicyAmendment> | null,
|
||||
/**
|
||||
* Ordered list of decisions the client may present for this prompt.
|
||||
*/
|
||||
availableDecisions?: Array<CommandExecutionApprovalDecision> | null, };
|
||||
proposedNetworkPolicyAmendments?: Array<NetworkPolicyAmendment> | null};
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type FileSystemSpecialPath = { "kind": "root" } | { "kind": "minimal" } | { "kind": "current_working_directory" } | { "kind": "project_roots", subpath: string | null, } | { "kind": "tmpdir" } | { "kind": "slash_tmp" } | { "kind": "unknown", path: string, subpath: string | null, };
|
||||
export type FileSystemSpecialPath = { "kind": "root" } | { "kind": "minimal" } | { "kind": "project_roots", subpath: string | null, } | { "kind": "tmpdir" } | { "kind": "slash_tmp" } | { "kind": "unknown", path: string, subpath: string | null, };
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
import type { PermissionProfileFileSystemPermissions } from "./PermissionProfileFileSystemPermissions";
|
||||
import type { PermissionProfileNetworkPermissions } from "./PermissionProfileNetworkPermissions";
|
||||
|
||||
export type PermissionProfile = { network: PermissionProfileNetworkPermissions | null, fileSystem: PermissionProfileFileSystemPermissions | null, };
|
||||
export type PermissionProfile = { "type": "managed", network: PermissionProfileNetworkPermissions, fileSystem: PermissionProfileFileSystemPermissions, } | { "type": "disabled" } | { "type": "external", network: PermissionProfileNetworkPermissions, };
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { FileSystemSandboxEntry } from "./FileSystemSandboxEntry";
|
||||
|
||||
export type PermissionProfileFileSystemPermissions = { entries: Array<FileSystemSandboxEntry>, globScanMaxDepth?: number, };
|
||||
export type PermissionProfileFileSystemPermissions = { "type": "restricted", entries: Array<FileSystemSandboxEntry>, globScanMaxDepth?: number, } | { "type": "unrestricted" };
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type PermissionProfileNetworkPermissions = { enabled: boolean | null, };
|
||||
export type PermissionProfileNetworkPermissions = { enabled: boolean, };
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
|
||||
export type ReadOnlyAccess = { "type": "restricted", includePlatformDefaults: boolean, readableRoots: Array<AbsolutePathBuf>, } | { "type": "fullAccess" };
|
||||
@@ -3,6 +3,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { NetworkAccess } from "./NetworkAccess";
|
||||
import type { ReadOnlyAccess } from "./ReadOnlyAccess";
|
||||
|
||||
export type SandboxPolicy = { "type": "dangerFullAccess" } | { "type": "readOnly", access: ReadOnlyAccess, networkAccess: boolean, } | { "type": "externalSandbox", networkAccess: NetworkAccess, } | { "type": "workspaceWrite", writableRoots: Array<AbsolutePathBuf>, readOnlyAccess: ReadOnlyAccess, networkAccess: boolean, excludeTmpdirEnvVar: boolean, excludeSlashTmp: boolean, };
|
||||
export type SandboxPolicy = { "type": "dangerFullAccess" } | { "type": "readOnly", networkAccess: boolean, } | { "type": "externalSandbox", networkAccess: NetworkAccess, } | { "type": "workspaceWrite", writableRoots: Array<AbsolutePathBuf>, networkAccess: boolean, excludeTmpdirEnvVar: boolean, excludeSlashTmp: boolean, };
|
||||
|
||||
@@ -5,7 +5,6 @@ import type { ServiceTier } from "../ServiceTier";
|
||||
import type { JsonValue } from "../serde_json/JsonValue";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
import type { AskForApproval } from "./AskForApproval";
|
||||
import type { PermissionProfile } from "./PermissionProfile";
|
||||
import type { SandboxMode } from "./SandboxMode";
|
||||
|
||||
/**
|
||||
@@ -18,27 +17,15 @@ import type { SandboxMode } from "./SandboxMode";
|
||||
* Prefer using thread_id whenever possible.
|
||||
*/
|
||||
export type ThreadForkParams = {threadId: string, /**
|
||||
* [UNSTABLE] Specify the rollout path to fork from.
|
||||
* If specified, the thread_id param will be ignored.
|
||||
*/
|
||||
path?: string | null, /**
|
||||
* Configuration overrides for the forked thread, if any.
|
||||
*/
|
||||
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
|
||||
* Override where approval requests are routed for review on this thread
|
||||
* and subsequent turns.
|
||||
*/
|
||||
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, /**
|
||||
* Full permissions override for the forked thread. Cannot be combined
|
||||
* with `sandbox`.
|
||||
*/
|
||||
permissionProfile?: PermissionProfile | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean, /**
|
||||
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean, /**
|
||||
* When true, return only thread metadata and live fork state without
|
||||
* populating `thread.turns`. This is useful when the client plans to call
|
||||
* `thread/turns/list` immediately after forking.
|
||||
*/
|
||||
excludeTurns?: boolean, /**
|
||||
* If true, persist additional rollout EventMsg variants required to
|
||||
* reconstruct a richer thread history on subsequent resume/fork/read.
|
||||
*/
|
||||
persistExtendedHistory: boolean};
|
||||
excludeTurns?: boolean};
|
||||
|
||||
@@ -6,28 +6,18 @@ import type { ReasoningEffort } from "../ReasoningEffort";
|
||||
import type { ServiceTier } from "../ServiceTier";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
import type { AskForApproval } from "./AskForApproval";
|
||||
import type { PermissionProfile } from "./PermissionProfile";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
import type { Thread } from "./Thread";
|
||||
|
||||
export type ThreadForkResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf,
|
||||
/**
|
||||
export type ThreadForkResponse = {thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf, /**
|
||||
* Instruction source files currently loaded for this thread.
|
||||
*/
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
||||
/**
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval, /**
|
||||
* Reviewer currently used for approval requests on this thread.
|
||||
*/
|
||||
approvalsReviewer: ApprovalsReviewer,
|
||||
/**
|
||||
approvalsReviewer: ApprovalsReviewer, /**
|
||||
* Legacy sandbox policy retained for compatibility. New clients should use
|
||||
* `permissionProfile` when present as the canonical active permissions
|
||||
* view.
|
||||
*/
|
||||
sandbox: SandboxPolicy,
|
||||
/**
|
||||
* Canonical active permissions view for this thread when representable.
|
||||
* This is `null` for external sandbox policies because external
|
||||
* enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||
*/
|
||||
permissionProfile: PermissionProfile | null, reasoningEffort: ReasoningEffort | null, };
|
||||
sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null};
|
||||
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoal.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoal.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ThreadGoalStatus } from "./ThreadGoalStatus";
|
||||
|
||||
export type ThreadGoal = { threadId: string, objective: string, status: ThreadGoalStatus, tokenBudget: number | null, tokensUsed: number, timeUsedSeconds: number, createdAt: number, updatedAt: number, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoalClearedNotification.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoalClearedNotification.ts
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ThreadGoalClearedNotification = { threadId: string, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoalStatus.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoalStatus.ts
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ThreadGoalStatus = "active" | "paused" | "budgetLimited" | "complete";
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoalUpdatedNotification.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadGoalUpdatedNotification.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ThreadGoal } from "./ThreadGoal";
|
||||
|
||||
export type ThreadGoalUpdatedNotification = { threadId: string, turnId: string | null, goal: ThreadGoal, };
|
||||
@@ -2,12 +2,10 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Personality } from "../Personality";
|
||||
import type { ResponseItem } from "../ResponseItem";
|
||||
import type { ServiceTier } from "../ServiceTier";
|
||||
import type { JsonValue } from "../serde_json/JsonValue";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
import type { AskForApproval } from "./AskForApproval";
|
||||
import type { PermissionProfile } from "./PermissionProfile";
|
||||
import type { SandboxMode } from "./SandboxMode";
|
||||
|
||||
/**
|
||||
@@ -22,32 +20,15 @@ import type { SandboxMode } from "./SandboxMode";
|
||||
* Prefer using thread_id whenever possible.
|
||||
*/
|
||||
export type ThreadResumeParams = {threadId: string, /**
|
||||
* [UNSTABLE] FOR CODEX CLOUD - DO NOT USE.
|
||||
* If specified, the thread will be resumed with the provided history
|
||||
* instead of loaded from disk.
|
||||
*/
|
||||
history?: Array<ResponseItem> | null, /**
|
||||
* [UNSTABLE] Specify the rollout path to resume from.
|
||||
* If specified, the thread_id param will be ignored.
|
||||
*/
|
||||
path?: string | null, /**
|
||||
* Configuration overrides for the resumed thread, if any.
|
||||
*/
|
||||
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
|
||||
* Override where approval requests are routed for review on this thread
|
||||
* and subsequent turns.
|
||||
*/
|
||||
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, /**
|
||||
* Full permissions override for the resumed thread. Cannot be combined
|
||||
* with `sandbox`.
|
||||
*/
|
||||
permissionProfile?: PermissionProfile | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /**
|
||||
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /**
|
||||
* When true, return only thread metadata and live-resume state without
|
||||
* populating `thread.turns`. This is useful when the client plans to call
|
||||
* `thread/turns/list` immediately after resuming.
|
||||
*/
|
||||
excludeTurns?: boolean, /**
|
||||
* If true, persist additional rollout EventMsg variants required to
|
||||
* reconstruct a richer thread history on subsequent resume/fork/read.
|
||||
*/
|
||||
persistExtendedHistory: boolean};
|
||||
excludeTurns?: boolean};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user