wile 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ This creates:
|
|
|
39
39
|
Set `WILE_REPO_SOURCE=local` in `.wile/secrets/.env` to run against the current directory without GitHub.
|
|
40
40
|
When `WILE_REPO_SOURCE=local`, GitHub credentials are optional.
|
|
41
41
|
Set `WILE_MAX_ITERATIONS` in `.wile/secrets/.env` to change the default loop limit (default: 25).
|
|
42
|
+
Optionally customize `.wile/Dockerfile` (created by `wile config`) to extend `wile-agent:base`.
|
|
42
43
|
Set `CODING_AGENT=CX` to use Codex CLI, `CODING_AGENT=OC` to use OpenCode (free native models), `CODING_AGENT=GC` to use Gemini CLI, otherwise `CODING_AGENT=CC` uses Claude Code.
|
|
43
44
|
|
|
44
45
|
## Run Wile
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR=$(cd "$(dirname "$0")/../../.." && pwd)
|
|
5
|
+
AGENT_DIR="$ROOT_DIR/packages/agent"
|
|
6
|
+
TMP_DIR=$(mktemp -d /tmp/wile-compact-custom-dockerfile-XXXXXX)
|
|
7
|
+
|
|
8
|
+
cleanup() {
|
|
9
|
+
rm -rf "$TMP_DIR"
|
|
10
|
+
}
|
|
11
|
+
trap cleanup EXIT INT TERM
|
|
12
|
+
|
|
13
|
+
mkdir -p "$TMP_DIR/.wile/secrets"
|
|
14
|
+
printf "secrets/\nscreenshots/\nlogs/\n" > "$TMP_DIR/.wile/.gitignore"
|
|
15
|
+
cp "$ROOT_DIR/scripts/fixtures/compact-prd.json" "$TMP_DIR/.wile/prd.json"
|
|
16
|
+
cp "$ROOT_DIR/scripts/fixtures/compact-progress.txt" "$TMP_DIR/.wile/progress.txt"
|
|
17
|
+
|
|
18
|
+
git -C "$TMP_DIR" init >/dev/null
|
|
19
|
+
git -C "$TMP_DIR" config user.email "test@local"
|
|
20
|
+
git -C "$TMP_DIR" config user.name "Wile Test"
|
|
21
|
+
git -C "$TMP_DIR" add .wile
|
|
22
|
+
git -C "$TMP_DIR" commit -m "seed compact custom dockerfile test" >/dev/null
|
|
23
|
+
|
|
24
|
+
cat > "$TMP_DIR/.wile/secrets/.env" <<'ENV'
|
|
25
|
+
CODING_AGENT=CC
|
|
26
|
+
CC_ANTHROPIC_API_KEY=dummy-key
|
|
27
|
+
CC_CLAUDE_MODEL=sonnet
|
|
28
|
+
WILE_REPO_SOURCE=local
|
|
29
|
+
WILE_MOCK_CLAUDE=true
|
|
30
|
+
ENV
|
|
31
|
+
|
|
32
|
+
cat > "$TMP_DIR/.wile/Dockerfile" <<'DOCKERFILE'
|
|
33
|
+
ARG WILE_BASE_IMAGE=wile-agent:base
|
|
34
|
+
FROM ${WILE_BASE_IMAGE}
|
|
35
|
+
|
|
36
|
+
USER root
|
|
37
|
+
RUN apt-get update \
|
|
38
|
+
&& apt-get install -y --no-install-recommends jq \
|
|
39
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
40
|
+
USER wile
|
|
41
|
+
DOCKERFILE
|
|
42
|
+
|
|
43
|
+
export WILE_AGENT_DIR="$AGENT_DIR"
|
|
44
|
+
cd "$TMP_DIR"
|
|
45
|
+
node "$ROOT_DIR/packages/cli/dist/cli.js" compact --max-iterations 1
|
|
46
|
+
|
|
47
|
+
LOG_FILE=$(ls "$TMP_DIR/.wile/logs"/compact-*.log | head -n 1)
|
|
48
|
+
if [ -z "$LOG_FILE" ]; then
|
|
49
|
+
echo "error: expected compact log file" >&2
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
grep -q "WILE - Compact PRD & Progress" "$LOG_FILE"
|
|
54
|
+
docker run --rm --entrypoint sh wile-agent:local -lc "command -v jq >/dev/null"
|
|
55
|
+
|
|
56
|
+
echo "test-compact-custom-dockerfile: ok"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR=$(cd "$(dirname "$0")/../../.." && pwd)
|
|
5
|
+
AGENT_DIR="$ROOT_DIR/packages/agent"
|
|
6
|
+
TMP_DIR=$(mktemp -d /tmp/wile-custom-dockerfile-XXXXXX)
|
|
7
|
+
|
|
8
|
+
cleanup() {
|
|
9
|
+
rm -rf "$TMP_DIR"
|
|
10
|
+
}
|
|
11
|
+
trap cleanup EXIT INT TERM
|
|
12
|
+
|
|
13
|
+
mkdir -p "$TMP_DIR/.wile/secrets"
|
|
14
|
+
printf "secrets/\nscreenshots/\nlogs/\n" > "$TMP_DIR/.wile/.gitignore"
|
|
15
|
+
|
|
16
|
+
cat > "$TMP_DIR/.wile/prd.json" <<'JSON'
|
|
17
|
+
{
|
|
18
|
+
"stories": [
|
|
19
|
+
{
|
|
20
|
+
"id": 1,
|
|
21
|
+
"title": "Custom dockerfile test",
|
|
22
|
+
"description": "Verify project Dockerfile extends Wile base image.",
|
|
23
|
+
"acceptanceCriteria": ["n/a"],
|
|
24
|
+
"dependsOn": [],
|
|
25
|
+
"status": "pending"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
JSON
|
|
30
|
+
|
|
31
|
+
cat > "$TMP_DIR/.wile/secrets/.env" <<'ENV'
|
|
32
|
+
CODING_AGENT=CC
|
|
33
|
+
ENV
|
|
34
|
+
|
|
35
|
+
cat > "$TMP_DIR/.wile/Dockerfile" <<'DOCKERFILE'
|
|
36
|
+
ARG WILE_BASE_IMAGE=wile-agent:base
|
|
37
|
+
FROM ${WILE_BASE_IMAGE}
|
|
38
|
+
|
|
39
|
+
USER root
|
|
40
|
+
RUN apt-get update \
|
|
41
|
+
&& apt-get install -y --no-install-recommends jq \
|
|
42
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
43
|
+
USER wile
|
|
44
|
+
DOCKERFILE
|
|
45
|
+
|
|
46
|
+
export WILE_AGENT_DIR="$AGENT_DIR"
|
|
47
|
+
cd "$TMP_DIR"
|
|
48
|
+
node "$ROOT_DIR/packages/cli/dist/cli.js" run --test --max-iterations 1
|
|
49
|
+
|
|
50
|
+
LOG_FILE=$(ls "$TMP_DIR/.wile/logs"/run-*.log | head -n 1)
|
|
51
|
+
if [ -z "$LOG_FILE" ]; then
|
|
52
|
+
echo "error: expected run log file" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
grep -q "TEST MODE" "$LOG_FILE"
|
|
57
|
+
docker run --rm --entrypoint sh wile-agent:local -lc "command -v jq >/dev/null"
|
|
58
|
+
|
|
59
|
+
echo "test-custom-dockerfile: ok"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR=$(cd "$(dirname "$0")/../../.." && pwd)
|
|
5
|
+
AGENT_DIR="$ROOT_DIR/packages/agent"
|
|
6
|
+
TMP_DIR=$(mktemp -d /tmp/wile-run-no-custom-XXXXXX)
|
|
7
|
+
|
|
8
|
+
cleanup() {
|
|
9
|
+
rm -rf "$TMP_DIR"
|
|
10
|
+
}
|
|
11
|
+
trap cleanup EXIT INT TERM
|
|
12
|
+
|
|
13
|
+
mkdir -p "$TMP_DIR/.wile/secrets"
|
|
14
|
+
printf "secrets/\nscreenshots/\nlogs/\n" > "$TMP_DIR/.wile/.gitignore"
|
|
15
|
+
|
|
16
|
+
cat > "$TMP_DIR/.wile/prd.json" <<'JSON'
|
|
17
|
+
{
|
|
18
|
+
"stories": [
|
|
19
|
+
{
|
|
20
|
+
"id": 1,
|
|
21
|
+
"title": "Default dockerfile fallback test",
|
|
22
|
+
"description": "Ensure run still works without .wile/Dockerfile",
|
|
23
|
+
"acceptanceCriteria": ["n/a"],
|
|
24
|
+
"dependsOn": [],
|
|
25
|
+
"status": "pending"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
JSON
|
|
30
|
+
|
|
31
|
+
cat > "$TMP_DIR/.wile/secrets/.env" <<'ENV'
|
|
32
|
+
CODING_AGENT=CC
|
|
33
|
+
ENV
|
|
34
|
+
|
|
35
|
+
if [ -f "$TMP_DIR/.wile/Dockerfile" ]; then
|
|
36
|
+
echo "error: .wile/Dockerfile should not exist for fallback test" >&2
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
export WILE_AGENT_DIR="$AGENT_DIR"
|
|
41
|
+
cd "$TMP_DIR"
|
|
42
|
+
OUTPUT_FILE="$TMP_DIR/output.txt"
|
|
43
|
+
node "$ROOT_DIR/packages/cli/dist/cli.js" run --test --max-iterations 1 --debug 2>&1 | tee "$OUTPUT_FILE"
|
|
44
|
+
|
|
45
|
+
grep -q "customDockerfile: (unset)" "$OUTPUT_FILE"
|
|
46
|
+
|
|
47
|
+
LOG_FILE=$(ls "$TMP_DIR/.wile/logs"/run-*.log | head -n 1)
|
|
48
|
+
if [ -z "$LOG_FILE" ]; then
|
|
49
|
+
echo "error: expected run log file" >&2
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
grep -q "TEST MODE" "$LOG_FILE"
|
|
54
|
+
grep -q "\"status\": \"done\"" "$TMP_DIR/.wile/prd.json"
|
|
55
|
+
|
|
56
|
+
echo "test-run-no-custom-dockerfile: ok"
|
package/dist/cli.js
CHANGED
|
@@ -7774,6 +7774,7 @@ var renderNonInteractiveConfigHelp = () => {
|
|
|
7774
7774
|
lines.push("- `branchName` (default `main`)");
|
|
7775
7775
|
lines.push("- `envProjectPath` (default `.wile/.env.project`)");
|
|
7776
7776
|
lines.push("- `maxIterations` (default `25`)");
|
|
7777
|
+
lines.push("- Optional custom Dockerfile: edit `.wile/Dockerfile` (created automatically by `wile config`)");
|
|
7777
7778
|
lines.push("- `ccModel` (`sonnet` | `opus` | `haiku`, default `opus`)");
|
|
7778
7779
|
lines.push("- `gcModel` (default `gemini-3-pro-preview`)");
|
|
7779
7780
|
lines.push("- `cxModel` (default `gpt-5.3-codex`)");
|
|
@@ -8063,6 +8064,7 @@ var runConfig = async (options = {}) => {
|
|
|
8063
8064
|
const additionalInstructionsPath = join(wileDir, "additional-instructions.md");
|
|
8064
8065
|
const preflightPath = join(wileDir, "preflight.md");
|
|
8065
8066
|
const agentsPath = join(wileDir, "AGENTS.md");
|
|
8067
|
+
const dockerfilePath = join(wileDir, "Dockerfile");
|
|
8066
8068
|
await mkdir(secretsDir, { recursive: true });
|
|
8067
8069
|
if (!nonInteractiveConfig) {
|
|
8068
8070
|
maybeInject();
|
|
@@ -8353,6 +8355,18 @@ Use bullet points for preflight checks, e.g.
|
|
|
8353
8355
|
- Run \`supabase db reset --db-url "$SUPABASE_DB_URL"\`.
|
|
8354
8356
|
-->
|
|
8355
8357
|
`);
|
|
8358
|
+
await writeIfMissing(dockerfilePath, [
|
|
8359
|
+
"ARG WILE_BASE_IMAGE=wile-agent:base",
|
|
8360
|
+
"FROM ${WILE_BASE_IMAGE}",
|
|
8361
|
+
"",
|
|
8362
|
+
"# Optional: install additional system dependencies for your project.",
|
|
8363
|
+
"# Example:",
|
|
8364
|
+
"# USER root",
|
|
8365
|
+
"# RUN apt-get update && apt-get install -y --no-install-recommends jq && rm -rf /var/lib/apt/lists/*",
|
|
8366
|
+
"# USER wile",
|
|
8367
|
+
""
|
|
8368
|
+
].join(`
|
|
8369
|
+
`));
|
|
8356
8370
|
await writeIfMissing(agentsPath, [
|
|
8357
8371
|
"# PRD authoring guidance for Wile",
|
|
8358
8372
|
"",
|
|
@@ -8432,6 +8446,13 @@ var resolveEnvProjectPath = (cwd, configured) => {
|
|
|
8432
8446
|
}
|
|
8433
8447
|
return defaultPath;
|
|
8434
8448
|
};
|
|
8449
|
+
var resolveAgentDockerfilePath = (cwd) => {
|
|
8450
|
+
const defaultPath = join2(cwd, ".wile", "Dockerfile");
|
|
8451
|
+
if (existsSync2(defaultPath)) {
|
|
8452
|
+
return defaultPath;
|
|
8453
|
+
}
|
|
8454
|
+
return;
|
|
8455
|
+
};
|
|
8435
8456
|
var parseEnvFile = (path) => {
|
|
8436
8457
|
if (!existsSync2(path)) {
|
|
8437
8458
|
return {};
|
|
@@ -8452,6 +8473,7 @@ var readWileConfig = (options = {}) => {
|
|
|
8452
8473
|
}
|
|
8453
8474
|
const { known: env } = splitEnv(parseEnvFile(paths.envPath));
|
|
8454
8475
|
const envProjectPath = resolveEnvProjectPath(options.cwd ?? process.cwd(), env.WILE_ENV_PROJECT_PATH);
|
|
8476
|
+
const agentDockerfile = resolveAgentDockerfilePath(options.cwd ?? process.cwd());
|
|
8455
8477
|
const envProject = parseEnvFile(envProjectPath);
|
|
8456
8478
|
const repoSource = env.WILE_REPO_SOURCE || "github";
|
|
8457
8479
|
if (validate) {
|
|
@@ -8485,6 +8507,7 @@ var readWileConfig = (options = {}) => {
|
|
|
8485
8507
|
githubRepoUrl: env.GITHUB_REPO_URL ?? "",
|
|
8486
8508
|
branchName: env.BRANCH_NAME ?? "",
|
|
8487
8509
|
repoSource,
|
|
8510
|
+
agentDockerfile,
|
|
8488
8511
|
ccClaudeModel: env.CC_CLAUDE_MODEL,
|
|
8489
8512
|
maxIterations: env.WILE_MAX_ITERATIONS,
|
|
8490
8513
|
ccClaudeCodeOauthToken: env.CC_CLAUDE_CODE_OAUTH_TOKEN,
|
|
@@ -8749,6 +8772,8 @@ import { existsSync as existsSync3, readFileSync as readFileSync3, mkdirSync, cr
|
|
|
8749
8772
|
import { spawn, spawnSync } from "node:child_process";
|
|
8750
8773
|
import { resolve as resolve3, join as join3, dirname } from "node:path";
|
|
8751
8774
|
import { fileURLToPath } from "node:url";
|
|
8775
|
+
var LOCAL_AGENT_IMAGE = "wile-agent:local";
|
|
8776
|
+
var BASE_AGENT_IMAGE = "wile-agent:base";
|
|
8752
8777
|
var findAgentDir = (startDir) => {
|
|
8753
8778
|
let current = startDir;
|
|
8754
8779
|
while (true) {
|
|
@@ -8784,14 +8809,43 @@ var validatePrdLocation = (paths) => {
|
|
|
8784
8809
|
throw new Error("Missing .wile/prd.json. Run 'bunx wile config'.");
|
|
8785
8810
|
}
|
|
8786
8811
|
};
|
|
8787
|
-
var
|
|
8788
|
-
const result = spawnSync("docker",
|
|
8789
|
-
stdio: "inherit"
|
|
8790
|
-
});
|
|
8812
|
+
var runDockerBuild = (args, errorMessage) => {
|
|
8813
|
+
const result = spawnSync("docker", args, { stdio: "inherit" });
|
|
8791
8814
|
if (result.status !== 0) {
|
|
8792
|
-
throw new Error(
|
|
8815
|
+
throw new Error(errorMessage);
|
|
8793
8816
|
}
|
|
8794
8817
|
};
|
|
8818
|
+
var validateCustomDockerfile = (dockerfilePath) => {
|
|
8819
|
+
const contents = readFileSync3(dockerfilePath, "utf8");
|
|
8820
|
+
if (contents.includes("WILE_BASE_IMAGE") || contents.includes(BASE_AGENT_IMAGE)) {
|
|
8821
|
+
return;
|
|
8822
|
+
}
|
|
8823
|
+
throw new Error([
|
|
8824
|
+
`Custom Dockerfile must extend ${BASE_AGENT_IMAGE}.`,
|
|
8825
|
+
`Update ${dockerfilePath} to include either:`,
|
|
8826
|
+
`- ARG WILE_BASE_IMAGE=${BASE_AGENT_IMAGE} + FROM \${WILE_BASE_IMAGE}`,
|
|
8827
|
+
`- FROM ${BASE_AGENT_IMAGE}`
|
|
8828
|
+
].join(`
|
|
8829
|
+
`));
|
|
8830
|
+
};
|
|
8831
|
+
var buildAgentImage = (agentDir, options) => {
|
|
8832
|
+
if (!options.customDockerfilePath) {
|
|
8833
|
+
runDockerBuild(["build", "-t", LOCAL_AGENT_IMAGE, agentDir], "Docker build failed.");
|
|
8834
|
+
return;
|
|
8835
|
+
}
|
|
8836
|
+
validateCustomDockerfile(options.customDockerfilePath);
|
|
8837
|
+
runDockerBuild(["build", "-t", BASE_AGENT_IMAGE, agentDir], "Docker base image build failed.");
|
|
8838
|
+
runDockerBuild([
|
|
8839
|
+
"build",
|
|
8840
|
+
"-t",
|
|
8841
|
+
LOCAL_AGENT_IMAGE,
|
|
8842
|
+
"--build-arg",
|
|
8843
|
+
`WILE_BASE_IMAGE=${BASE_AGENT_IMAGE}`,
|
|
8844
|
+
"-f",
|
|
8845
|
+
options.customDockerfilePath,
|
|
8846
|
+
options.projectDir
|
|
8847
|
+
], "Custom Docker build failed.");
|
|
8848
|
+
};
|
|
8795
8849
|
var resolveAgentDir = () => {
|
|
8796
8850
|
const override = process.env.WILE_AGENT_DIR;
|
|
8797
8851
|
if (override && existsSync3(override)) {
|
|
@@ -8880,7 +8934,7 @@ var buildDockerArgs = (options, config, paths, cwd, extraEnv = []) => {
|
|
|
8880
8934
|
dockerArgs.push("-e", `WILE_ADDITIONAL_INSTRUCTIONS=${additionalInstructionsPath}`);
|
|
8881
8935
|
dockerArgs.push("-v", `${additionalInstructionsPath}:${additionalInstructionsPath}`);
|
|
8882
8936
|
}
|
|
8883
|
-
dockerArgs.push(
|
|
8937
|
+
dockerArgs.push(LOCAL_AGENT_IMAGE);
|
|
8884
8938
|
return dockerArgs;
|
|
8885
8939
|
};
|
|
8886
8940
|
var runWile = async (options) => {
|
|
@@ -8903,6 +8957,7 @@ var runWile = async (options) => {
|
|
|
8903
8957
|
console.log(`- WILE_AGENT_DIR: ${process.env.WILE_AGENT_DIR ?? "(unset)"}`);
|
|
8904
8958
|
console.log(`- codingAgent: ${config.codingAgent}`);
|
|
8905
8959
|
console.log(`- repoSource: ${config.repoSource}`);
|
|
8960
|
+
console.log(`- customDockerfile: ${config.agentDockerfile ?? "(unset)"}`);
|
|
8906
8961
|
console.log(`- githubRepoUrl: ${config.githubRepoUrl || "(empty)"}`);
|
|
8907
8962
|
console.log(`- branchName: ${config.branchName || "(empty)"}`);
|
|
8908
8963
|
}
|
|
@@ -8929,7 +8984,10 @@ var runWile = async (options) => {
|
|
|
8929
8984
|
}
|
|
8930
8985
|
const agentDir = resolveAgentDir();
|
|
8931
8986
|
const resolvedIterations = options.maxIterations || config.maxIterations || "25";
|
|
8932
|
-
buildAgentImage(agentDir
|
|
8987
|
+
buildAgentImage(agentDir, {
|
|
8988
|
+
projectDir: cwd,
|
|
8989
|
+
customDockerfilePath: config.agentDockerfile
|
|
8990
|
+
});
|
|
8933
8991
|
const dockerArgs = buildDockerArgs({ ...options, maxIterations: resolvedIterations }, config, paths, cwd);
|
|
8934
8992
|
const logsDir = join3(paths.wileDir, "logs");
|
|
8935
8993
|
mkdirSync(logsDir, { recursive: true });
|
|
@@ -8973,6 +9031,7 @@ var runCompact = async (options) => {
|
|
|
8973
9031
|
console.log(`- WILE_AGENT_DIR: ${process.env.WILE_AGENT_DIR ?? "(unset)"}`);
|
|
8974
9032
|
console.log(`- codingAgent: ${config.codingAgent}`);
|
|
8975
9033
|
console.log(`- repoSource: ${config.repoSource}`);
|
|
9034
|
+
console.log(`- customDockerfile: ${config.agentDockerfile ?? "(unset)"}`);
|
|
8976
9035
|
console.log(`- githubRepoUrl: ${config.githubRepoUrl || "(empty)"}`);
|
|
8977
9036
|
console.log(`- branchName: ${config.branchName || "(empty)"}`);
|
|
8978
9037
|
}
|
|
@@ -8996,7 +9055,10 @@ var runCompact = async (options) => {
|
|
|
8996
9055
|
}
|
|
8997
9056
|
const agentDir = resolveAgentDir();
|
|
8998
9057
|
const resolvedIterations = options.maxIterations || "1";
|
|
8999
|
-
buildAgentImage(agentDir
|
|
9058
|
+
buildAgentImage(agentDir, {
|
|
9059
|
+
projectDir: cwd,
|
|
9060
|
+
customDockerfilePath: config.agentDockerfile
|
|
9061
|
+
});
|
|
9000
9062
|
const dockerArgs = buildDockerArgs({ ...options, maxIterations: resolvedIterations }, config, paths, cwd, ["WILE_MODE=compact"]);
|
|
9001
9063
|
const logsDir = join4(paths.wileDir, "logs");
|
|
9002
9064
|
mkdirSync2(logsDir, { recursive: true });
|