Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8a8fea9
feat(config): add codex tool mode
Waishnav Jun 21, 2026
908c9a0
feat(tools): add workspace-confined patch engine
Waishnav Jun 21, 2026
a0e6caa
feat(tools): expose apply_patch in codex mode
Waishnav Jun 21, 2026
60c43dc
feat(exec): add resumable process session manager
Waishnav Jun 21, 2026
a4aa58a
feat(exec): expose exec_command and write_stdin
Waishnav Jun 21, 2026
e3938ca
feat(exec): support optional PTY sessions
Waishnav Jun 21, 2026
4fc552d
fix(exec): terminate spawned process groups
Waishnav Jun 21, 2026
6d54923
docs: document codex mode QA and rollout
Waishnav Jun 21, 2026
e70e9bc
fix(config): keep codex tool names stable
Waishnav Jun 21, 2026
b9c0933
feat(ui): add codex tool card payloads
Waishnav Jun 22, 2026
0164595
feat(ui): render codex tool cards
Waishnav Jun 22, 2026
ee1dd50
fix(exec): wait for interrupted process exit
Waishnav Jun 22, 2026
d6bff09
fix(exec): wait after process interactions
Waishnav Jun 22, 2026
ab72d84
refactor(exec): isolate platform shell selection
Waishnav Jun 22, 2026
4d5a37c
fix(exec): terminate process trees on Windows
Waishnav Jun 22, 2026
d02ac26
fix(patch): replace existing files on Windows
Waishnav Jun 22, 2026
fa62642
test(tools): account for cross-platform semantics
Waishnav Jun 22, 2026
557d813
fix(exec): quote Windows commands consistently
Waishnav Jun 22, 2026
fbd45d1
fix(deps): use portable node-pty prebuilds
Waishnav Jun 22, 2026
7eaf319
test(exec): remove timing-only output assertion
Waishnav Jun 22, 2026
fb1a8d9
test(exec): decouple interrupt from output timing
Waishnav Jun 22, 2026
4a672e9
fix(exec): delegate pipe shell quoting to Node
Waishnav Jun 22, 2026
75c2ff6
fix(exec): pass raw commands to Windows PTYs
Waishnav Jun 22, 2026
e3c59e9
test(exec): quote Windows executable paths natively
Waishnav Jun 22, 2026
f900ade
fix(exec): preserve Windows PTY command lines
Waishnav Jun 22, 2026
5bd5af7
test(exec): clean up PTYs after assertions
Waishnav Jun 22, 2026
db8f995
test(exec): avoid PTY line discipline assumptions
Waishnav Jun 22, 2026
afdd4f6
test(exec): use native Windows PTY smoke command
Waishnav Jun 22, 2026
4620f86
fix(exec): pass raw Windows PTY commands
Waishnav Jun 22, 2026
402e94c
fix(deps): update Windows PTY handle fixes
Waishnav Jun 22, 2026
e49cb56
fix(exec): run Windows PTYs through temp scripts
Waishnav Jun 22, 2026
814e1d4
fix(exec): guard Windows PTY listener setup
Waishnav Jun 22, 2026
c1caac5
fix(deps): repair stable node-pty on macOS
Waishnav Jun 22, 2026
3109b22
fix(exec): delay Windows PTY command startup
Waishnav Jun 22, 2026
3988be8
fix(exec): omit PTY signals on Windows
Waishnav Jun 22, 2026
4f1feee
test(exec): allow hosted Windows PTY startup
Waishnav Jun 22, 2026
64319c6
fix(exec): exit Windows PTY scripts explicitly
Waishnav Jun 22, 2026
14ed5f2
fix(deps): combine PTY platform repairs
Waishnav Jun 22, 2026
58f014b
fix(exec): use native Windows PTY command lines
Waishnav Jun 22, 2026
be986c5
fix(exec): start Windows PTYs after listeners
Waishnav Jun 22, 2026
e7cd9fe
fix(exec): fall back from Windows native PTYs
Waishnav Jun 22, 2026
3fd16f1
fix(deps): retain stable Unix PTY support
Waishnav Jun 22, 2026
17fa037
fix(deps): normalize optional pty lock entry
Waishnav Jun 28, 2026
7dfe985
feat: preserve head and tail process output
Waishnav Jun 29, 2026
474aeb8
feat: normalize codex command sessions
Waishnav Jun 29, 2026
7510c54
feat: use numeric process session ids
Waishnav Jun 29, 2026
b43d85f
feat: align apply patch semantics with codex
Waishnav Jun 29, 2026
960fd78
docs: clarify codex patch semantics
Waishnav Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/chatgpt-coding-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,20 @@ Legacy names are available with `DEVSPACE_TOOL_NAMING=legacy`:

Use `DEVSPACE_TOOL_MODE=full` to restore dedicated search and directory tools.

The experimental Codex-style surface is enabled with
`DEVSPACE_TOOL_MODE=codex`. It exposes:

- `open_workspace`
- `read`
- `apply_patch`
- `exec_command`
- `write_stdin`

In this mode, `write`, `edit`, `bash`, `grep`, `glob`, and `ls` are not
registered. `exec_command` returns a process session ID when a command is still
running after its yield window. Use `write_stdin` to poll it, send input, resize
a PTY, or send Ctrl-C. Set `tty: true` only for commands that need a terminal.

## Show Changes

By default, `DEVSPACE_WIDGETS=full`.
Expand Down
73 changes: 73 additions & 0 deletions docs/codex-tool-mode-qa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Codex Tool Mode Manual QA

Run these checks against a disposable Git repository inside an allowed DevSpace
root. Keep the DevSpace server logs visible during the test.

## Setup

1. Build the current branch with `npm ci && npm run build`.
2. Start DevSpace with `DEVSPACE_TOOL_MODE=codex devspace serve`.
3. Connect or refresh the DevSpace connector in ChatGPT.
4. Open the disposable repository with `open_workspace`.
5. Confirm the core tools are `open_workspace`, `read`, `apply_patch`,
`exec_command`, and `write_stdin`.
6. Confirm `write`, `edit`, `bash`, `grep`, `glob`, and `ls` are absent.
7. If `DEVSPACE_WIDGETS=changes`, also expect `show_changes`.

## Apply Patch

1. Add a text file containing multiple lines and a blank line.
2. Update two separate regions of that file in one patch.
3. Create a nested file, rename it, and then delete it.
4. Patch an existing CRLF file and verify it remains CRLF.
5. Verify executable permissions survive an update and a move.
6. Try to add `../outside.txt`; confirm the tool rejects the path.
7. Patch through a symlink targeting an external directory; confirm rejection.
8. Submit a hunk whose context is absent; confirm no file from that patch changes.
9. With changes widgets enabled, inspect the aggregate diff.

## Foreground Commands

1. Run `pwd` and confirm it reports the opened workspace.
Comment thread
Waishnav marked this conversation as resolved.
2. Run a command in a relative `workingDirectory` and confirm the directory.
3. Write to stdout and stderr; confirm both appear.
4. Exit nonzero; confirm `running=false` and the exit code.
5. Use a small output budget on a noisy command; confirm truncation is reported.

## Background Sessions

1. Start a delayed command with a short yield time.
2. Confirm `exec_command` returns `running=true` and a `sessionId`.
3. Poll with empty `chars`; confirm output is not duplicated.
4. Poll until completion; confirm the final exit code and no `sessionId`.
5. Poll the completed session again; confirm it is unknown.
6. Reconnect MCP without restarting DevSpace and confirm polling still works.
7. Restart DevSpace and confirm old process session IDs are invalid.

## Input, Interrupt, And PTY

1. Start a program that reads stdin without a PTY and send it a line.
2. Start a long-running process and send `\u0003`; confirm it stops.
3. Start an interactive program with `tty=true`; confirm it detects a TTY.
4. Resize a PTY from 80x24 to 120x30 and verify the observed dimensions.
5. Omit optional dependencies; normal commands must work and `tty=true` must
return the explicit `node-pty` error.
Comment thread
Waishnav marked this conversation as resolved.

## Cleanup

1. Start a non-PTY command that creates a long-running child process.
2. Stop DevSpace with SIGINT and verify both shell and child exit.
3. Repeat with a PTY command.
4. Confirm no process remains after server exit.
5. Repeat session cycles and check that memory use does not steadily increase.

## Existing Mode Regression

1. Start without `DEVSPACE_TOOL_MODE`; confirm `minimal` remains the default.
2. Minimal must expose `read`, `write`, `edit`, and `bash`, but not Codex tools
or dedicated search tools.
3. `DEVSPACE_TOOL_MODE=full` must add `grep`, `glob`, and `ls`.
4. With no explicit mode, `DEVSPACE_MINIMAL_TOOLS=1` maps to minimal and `0`
maps to full.
5. Set `DEVSPACE_TOOL_MODE=codex` with `DEVSPACE_MINIMAL_TOOLS=0`; confirm the
explicit Codex mode wins.
15 changes: 13 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,19 @@ MCP clients discover metadata from:

| Value | Behavior |
| --- | --- |
| `minimal` | Default. Disables dedicated search and list tools. Clients use the shell tool with `rg`, `grep`, `find`, `ls`, or `tree` for inspection. |
| `full` | Enables dedicated `grep`, `glob`, and `ls` tools. |
| `minimal` | Default. Exposes `open_workspace`, `read`, `write`, `edit`, and `bash`. Clients use `bash` with tools such as `rg`, `find`, and `ls` for inspection. |
| `full` | Exposes the minimal tools plus dedicated `grep`, `glob`, and `ls` tools. |
| `codex` | Experimental. Exposes `open_workspace`, `read`, `apply_patch`, `exec_command`, and `write_stdin`. Existing mutation and shell tools are hidden. |

`DEVSPACE_MINIMAL_TOOLS` remains a backward-compatible alias when
`DEVSPACE_TOOL_MODE` is unset: `1` selects `minimal` and `0` selects `full`.
The `codex` mode must be selected through `DEVSPACE_TOOL_MODE` and always uses
its fixed short tool names regardless of `DEVSPACE_TOOL_NAMING`.

Codex-mode commands run without a PTY by default. Set `tty: true` on
`exec_command` for interactive terminal programs. PTY support uses the optional
`node-pty` dependency; `write_stdin` can send input, poll output, and resize PTY
sessions.

## Widgets

Expand Down
24 changes: 23 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
"build": "npm run clean && npm run build:app && tsc -p tsconfig.build.json",
"build:app": "vite build",
"dev": "node scripts/dev-server.mjs",
"postinstall": "node scripts/fix-node-pty-permissions.mjs",
"start": "node dist/cli.js serve",
"test": "tsx src/config.test.ts && tsx src/roots.test.ts && tsx src/skills.test.ts && tsx src/workspaces.test.ts && tsx src/review-checkpoints.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts",
"test": "tsx src/config.test.ts && tsx src/ui/card-types.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/roots.test.ts && tsx src/skills.test.ts && tsx src/workspaces.test.ts && tsx src/review-checkpoints.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"keywords": [],
Expand Down Expand Up @@ -61,5 +62,8 @@
"protobufjs": "7.6.4",
"ws": "8.21.0",
"undici": "8.5.0"
},
"optionalDependencies": {
"node-pty": "^1.1.0"
}
}
22 changes: 22 additions & 0 deletions scripts/fix-node-pty-permissions.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { chmod } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";

if (process.platform === "darwin") {
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
for (const architecture of ["arm64", "x64"]) {
const helper = resolve(
projectRoot,
"node_modules",
"node-pty",
"prebuilds",
`darwin-${architecture}`,
"spawn-helper",
);
try {
await chmod(helper, 0o755);
} catch (error) {
if (error.code !== "ENOENT") throw error;
}
}
}
Loading
Loading