@elie-laloum/outpost 1.1.3 → 2.0.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/CHANGELOG.md +20 -0
- package/README.md +12 -6
- package/dist/cli/image.js +1 -1
- package/dist/cli/image.js.map +1 -1
- package/dist/cli/init-command.js +4 -3
- package/dist/cli/init-command.js.map +1 -1
- package/dist/cli/main.constants.d.ts +4 -10
- package/dist/cli/main.constants.js +4 -7
- package/dist/cli/main.constants.js.map +1 -1
- package/dist/cli/project-settings.js +8 -2
- package/dist/cli/project-settings.js.map +1 -1
- package/dist/cli/scaffold-files.d.ts +1 -1
- package/dist/cli/scaffold-files.js +26 -20
- package/dist/cli/scaffold-files.js.map +1 -1
- package/dist/cli/scaffold-validation.js +2 -5
- package/dist/cli/scaffold-validation.js.map +1 -1
- package/dist/cli/scaffold.constants.d.ts +0 -2
- package/dist/cli/scaffold.constants.js +2 -13
- package/dist/cli/scaffold.constants.js.map +1 -1
- package/dist/cli/scaffold.d.ts +1 -1
- package/dist/cli/scaffold.js +37 -29
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli/scaffold.types.d.ts +3 -5
- package/dist/cli/scaffold.types.js.map +1 -1
- package/dist/cli/starters.d.ts +1 -2
- package/dist/cli/starters.js +42 -30
- package/dist/cli/starters.js.map +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/binary-process.d.ts +3 -0
- package/dist/infrastructure/binary-process.js +53 -0
- package/dist/infrastructure/binary-process.js.map +1 -0
- package/dist/infrastructure/binary-process.types.d.ts +5 -0
- package/dist/infrastructure/binary-process.types.js +2 -0
- package/dist/infrastructure/binary-process.types.js.map +1 -0
- package/dist/infrastructure/transfer-copy.d.ts +3 -0
- package/dist/infrastructure/transfer-copy.js +51 -0
- package/dist/infrastructure/transfer-copy.js.map +1 -0
- package/dist/providers/container-archive.d.ts +3 -0
- package/dist/providers/container-archive.js +27 -0
- package/dist/providers/container-archive.js.map +1 -0
- package/dist/providers/container-command.js +3 -3
- package/dist/providers/container-command.js.map +1 -1
- package/dist/providers/container-files.d.ts +2 -1
- package/dist/providers/container-files.js +100 -11
- package/dist/providers/container-files.js.map +1 -1
- package/dist/providers/container.js +11 -2
- package/dist/providers/container.js.map +1 -1
- package/package.json +1 -1
- package/dist/adapters/backlogs/backlog.constants.d.ts +0 -4
- package/dist/adapters/backlogs/backlog.constants.js +0 -5
- package/dist/adapters/backlogs/backlog.constants.js.map +0 -1
- package/dist/adapters/backlogs/beads-adapter.d.ts +0 -4
- package/dist/adapters/backlogs/beads-adapter.js +0 -31
- package/dist/adapters/backlogs/beads-adapter.js.map +0 -1
- package/dist/adapters/backlogs/cli.d.ts +0 -3
- package/dist/adapters/backlogs/cli.js +0 -20
- package/dist/adapters/backlogs/cli.js.map +0 -1
- package/dist/adapters/backlogs/github-adapter.d.ts +0 -4
- package/dist/adapters/backlogs/github-adapter.js +0 -28
- package/dist/adapters/backlogs/github-adapter.js.map +0 -1
- package/dist/adapters/backlogs/issue.d.ts +0 -2
- package/dist/adapters/backlogs/issue.js +0 -13
- package/dist/adapters/backlogs/issue.js.map +0 -1
- package/dist/adapters/backlogs/settings.types.d.ts +0 -5
- package/dist/adapters/backlogs/settings.types.js +0 -2
- package/dist/adapters/backlogs/settings.types.js.map +0 -1
- package/dist/application/campaign-integration.d.ts +0 -2
- package/dist/application/campaign-integration.js +0 -44
- package/dist/application/campaign-integration.js.map +0 -1
- package/dist/application/campaign-planner.d.ts +0 -3
- package/dist/application/campaign-planner.js +0 -35
- package/dist/application/campaign-planner.js.map +0 -1
- package/dist/application/campaign-worker.d.ts +0 -3
- package/dist/application/campaign-worker.js +0 -54
- package/dist/application/campaign-worker.js.map +0 -1
- package/dist/application/campaign.constants.d.ts +0 -7
- package/dist/application/campaign.constants.js +0 -8
- package/dist/application/campaign.constants.js.map +0 -1
- package/dist/application/campaign.d.ts +0 -3
- package/dist/application/campaign.js +0 -96
- package/dist/application/campaign.js.map +0 -1
- package/dist/application/campaign.types.d.ts +0 -43
- package/dist/application/campaign.types.js +0 -2
- package/dist/application/campaign.types.js.map +0 -1
- package/dist/domain/backlog.d.ts +0 -3
- package/dist/domain/backlog.js +0 -23
- package/dist/domain/backlog.js.map +0 -1
- package/dist/domain/backlog.types.d.ts +0 -15
- package/dist/domain/backlog.types.js +0 -2
- package/dist/domain/backlog.types.js.map +0 -1
- package/dist/providers/backlogs.d.ts +0 -3
- package/dist/providers/backlogs.js +0 -3
- package/dist/providers/backlogs.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
- Normalize the workflow test directory before computing relative repository paths, fixing macOS CI with symlinked temporary directories.
|
|
6
|
+
- Show live agent progress in generated starters and report cancellation recovery details without an uncaught error stack trace.
|
|
7
|
+
- Document workflow directories, repository path resolution and multi-repository task ownership in English and French.
|
|
8
|
+
- Generate standalone workflow projects directly in the chosen directory, with `run.ts`, a default package manifest and preserved existing package/ignore files.
|
|
9
|
+
- Add `init --repository` for external repositories; resolve generated brief/environment paths from the script and pin the workflow container image independently of the target repository.
|
|
10
|
+
- Read image build recipes from the workflow root; older layouts can use `--file .outpost/Dockerfile`.
|
|
11
|
+
- Remove issue campaigns, GitHub/Beads/custom backlog connectors and their public types.
|
|
12
|
+
- Simplify initialization to a dispatch starter; remove campaign templates, `--template`, `--tracker`, `--label`, tracker files and GitHub/Beads CLI installation.
|
|
13
|
+
|
|
14
|
+
## 1.1.4
|
|
15
|
+
|
|
16
|
+
- Wait for noninteractive container commands and preserve their real exit status; reuse the runtime terminal for interactive commands.
|
|
17
|
+
- Stream binary archives through the running Docker/Podman container so uploads and conversation capture/restore see the same tmpfs home as agents.
|
|
18
|
+
- Preserve ordinary file modes and links, reject unsafe download destinations, and support GNU tar and bsdtar hosts.
|
|
19
|
+
- Create a private writable agent home in generated images, including when used without the sandbox tmpfs mount.
|
|
20
|
+
- Add real container, pseudo-terminal, cancellation, binary integrity and native conversation regression checks.
|
|
21
|
+
- Add English/French account-connection guides for Claude Code and Codex, plus seven progressive cookbooks.
|
|
22
|
+
|
|
3
23
|
## 1.1.3
|
|
4
24
|
|
|
5
25
|
- Replace the flat documentation with an Astro Starlight site in English and French, with English as the default language.
|
package/README.md
CHANGED
|
@@ -6,20 +6,23 @@ Outpost is a TypeScript library for running coding agents in reusable sandboxes,
|
|
|
6
6
|
|
|
7
7
|
## Get started
|
|
8
8
|
|
|
9
|
-
Requires Node.js **24+**, Git,
|
|
9
|
+
Requires Node.js **24+**, Git, a target repository with a commit, and the credentials of your chosen agent. The workflow can live in its own directory. This example uses Docker.
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
mkdir workflow1
|
|
13
|
+
cd workflow1
|
|
14
|
+
npx @elie-laloum/outpost init --yes --repository /path1/repository --install --build
|
|
14
15
|
```
|
|
15
16
|
|
|
16
|
-
Copy `.
|
|
17
|
+
Copy `.env.example` to `.env` and declare `OPENAI_API_KEY`. An empty declaration inherits the matching process variable. Then run the generated script:
|
|
17
18
|
|
|
18
19
|
```sh
|
|
19
|
-
node
|
|
20
|
+
node run.ts "Add validation, run tests and commit the change"
|
|
20
21
|
```
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
`init` creates `package.json`, `run.ts`, `brief.md`, `.env.example`, `.gitignore` and a container recipe directly in the workflow directory. Existing package manifests are preserved; explicit CommonJS projects get `run.mts` for compatibility. The script resolves its brief, environment and relative repository paths from its own directory. See [multi-repository workflows](https://elie-laloum.github.io/outpost/workflows/sandbox-tasks/) to orchestrate several repositories.
|
|
24
|
+
|
|
25
|
+
For Codex API-key authentication, add the login hook from [Connect Codex](https://elie-laloum.github.io/outpost/agents/connect-codex/) before dispatching.
|
|
23
26
|
|
|
24
27
|
## Use the library
|
|
25
28
|
|
|
@@ -27,6 +30,7 @@ Use `run.ts` for a project with `"type": "module"`; initialization prints the ex
|
|
|
27
30
|
import { dispatch, codex } from "@elie-laloum/outpost";
|
|
28
31
|
|
|
29
32
|
const result = await dispatch({
|
|
33
|
+
repository: "/path1/repository",
|
|
30
34
|
agent: codex(),
|
|
31
35
|
branch: { mode: "integrate" },
|
|
32
36
|
brief: { text: "Fix the failing tests, verify and commit." },
|
|
@@ -34,6 +38,8 @@ const result = await dispatch({
|
|
|
34
38
|
console.log(result.branch, result.commits);
|
|
35
39
|
```
|
|
36
40
|
|
|
41
|
+
`repository` selects a local Git checkout; without it, library calls use the current working directory. See [repository paths](https://elie-laloum.github.io/outpost/sandboxes/repositories/) for external checkouts and paths relative to the workflow script.
|
|
42
|
+
|
|
37
43
|
Learn about [sandboxes](https://elie-laloum.github.io/outpost/sandboxes/lifecycle/), [workflows](https://elie-laloum.github.io/outpost/workflows/graph/), [providers](https://elie-laloum.github.io/outpost/providers/overview/) and [recovery](https://elie-laloum.github.io/outpost/operations/recovery/) in the English/French documentation. The [roadmap](https://elie-laloum.github.io/outpost/project/roadmap/) describes future work.
|
|
38
44
|
|
|
39
45
|
## Development
|
package/dist/cli/image.js
CHANGED
|
@@ -18,7 +18,7 @@ export async function manageImage(action, options = {}, executor) {
|
|
|
18
18
|
"--tag",
|
|
19
19
|
image,
|
|
20
20
|
"--file",
|
|
21
|
-
resolve(root, options.file ??
|
|
21
|
+
resolve(root, options.file ?? imageFiles[engine]),
|
|
22
22
|
"--build-arg",
|
|
23
23
|
`AGENT_UID=${uid}`,
|
|
24
24
|
"--build-arg",
|
package/dist/cli/image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/cli/image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGjE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAA0B,EAC1B,UAAwB,EAAE,EAC1B,QAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,EACtD,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,EACnC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3C,SAAS,CACP,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,EAC1C,uCAAuC,CACxC,CAAC;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,aAAa,CAAC,GAAG,EAChE,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,aAAa,CAAC,GAAG,CAAC;IAC/D,SAAS,CACP,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC;QACvB,GAAG,IAAI,CAAC;QACR,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC;QACzB,GAAG,IAAI,CAAC,EACV,0CAA0C,CAC3C,CAAC;IACF,MAAM,IAAI,GACR,MAAM,KAAK,QAAQ;QACjB,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC;QACxB,CAAC,CAAC;YACE,OAAO;YACP,OAAO;YACP,KAAK;YACL,QAAQ;YACR,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/cli/image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGjE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAA0B,EAC1B,UAAwB,EAAE,EAC1B,QAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,EACtD,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,EACnC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3C,SAAS,CACP,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,EAC1C,uCAAuC,CACxC,CAAC;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,aAAa,CAAC,GAAG,EAChE,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,aAAa,CAAC,GAAG,CAAC;IAC/D,SAAS,CACP,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC;QACvB,GAAG,IAAI,CAAC;QACR,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC;QACzB,GAAG,IAAI,CAAC,EACV,0CAA0C,CAC3C,CAAC;IACF,MAAM,IAAI,GACR,MAAM,KAAK,QAAQ;QACjB,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC;QACxB,CAAC,CAAC;YACE,OAAO;YACP,OAAO;YACP,KAAK;YACL,QAAQ;YACR,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;YACjD,aAAa;YACb,aAAa,GAAG,EAAE;YAClB,aAAa;YACb,aAAa,GAAG,EAAE;YAClB,IAAI;SACL,CAAC;IACR,MAAM,cAAc,CAClB;QACE,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,aAAa,CAAC,OAAO;QACjC,OAAO,CAAC,OAAO,EAAE,IAAI;YACnB,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;KACF,EACD,QAAQ,CACT,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { resolve } from \"node:path\";\nimport { invariant } from \"../domain/errors.ts\";\nimport { requireSuccess } from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { imageName } from \"../providers/container.ts\";\nimport { imageDefaults, imageFiles } from \"./image.constants.ts\";\nimport type { ImageOptions } from \"./image.types.ts\";\n\nexport async function manageImage(\n action: \"build\" | \"remove\",\n options: ImageOptions = {},\n executor?: Executor,\n): Promise<string> {\n const root = resolve(options.directory ?? process.cwd()),\n engine = options.engine ?? \"docker\",\n image = options.image ?? imageName(root);\n invariant(\n engine === \"docker\" || engine === \"podman\",\n \"Image engine must be docker or podman\",\n );\n const uid = options.uid ?? process.getuid?.() ?? imageDefaults.uid,\n gid = options.gid ?? process.getgid?.() ?? imageDefaults.gid;\n invariant(\n Number.isSafeInteger(uid) &&\n uid >= 0 &&\n Number.isSafeInteger(gid) &&\n gid >= 0,\n \"UID and GID must be nonnegative integers\",\n );\n const args =\n action === \"remove\"\n ? [\"image\", \"rm\", image]\n : [\n \"build\",\n \"--tag\",\n image,\n \"--file\",\n resolve(root, options.file ?? imageFiles[engine]),\n \"--build-arg\",\n `AGENT_UID=${uid}`,\n \"--build-arg\",\n `AGENT_GID=${gid}`,\n root,\n ];\n await requireSuccess(\n {\n executable: engine,\n arguments: args,\n directory: root,\n deadlineMs: imageDefaults.buildMs,\n observe(channel, text) {\n (channel === \"stdout\" ? process.stdout : process.stderr).write(text);\n },\n },\n executor,\n );\n return image;\n}\n"]}
|
package/dist/cli/init-command.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
1
2
|
import { createInterface } from "node:readline/promises";
|
|
2
3
|
import { initializationQuestions } from "./main.constants.js";
|
|
3
4
|
import { initialize } from "./scaffold.js";
|
|
@@ -5,8 +6,8 @@ export async function initializeCommand({ values, }) {
|
|
|
5
6
|
const options = Object.fromEntries(Object.entries(values).filter(([key]) => !["help", "yes"].includes(key)));
|
|
6
7
|
if (!values.yes &&
|
|
7
8
|
!process.stdin.isTTY &&
|
|
8
|
-
(!values.agent || !values.provider
|
|
9
|
-
throw new Error("Headless initialization requires --yes for defaults, or --agent
|
|
9
|
+
(!values.agent || !values.provider))
|
|
10
|
+
throw new Error("Headless initialization requires --yes for defaults, or --agent and --provider.");
|
|
10
11
|
if (!values.yes && process.stdin.isTTY) {
|
|
11
12
|
const terminal = createInterface({
|
|
12
13
|
input: process.stdin,
|
|
@@ -24,6 +25,6 @@ export async function initializeCommand({ values, }) {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
const result = await initialize(options);
|
|
27
|
-
process.stdout.write(`
|
|
28
|
+
process.stdout.write(`Initialized ${result.files.length} files in ${resolve(values.directory ?? process.cwd())}.\nRun: ${result.run}\n`);
|
|
28
29
|
}
|
|
29
30
|
//# sourceMappingURL=init-command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-command.js","sourceRoot":"","sources":["../../src/cli/init-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,MAAM,GACQ;IACd,MAAM,OAAO,GAA4B,MAAM,CAAC,WAAW,CACzD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CACzE,CAAC;IACF,IACE,CAAC,MAAM,CAAC,GAAG;QACX,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QACpB,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"init-command.js","sourceRoot":"","sources":["../../src/cli/init-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,MAAM,GACQ;IACd,MAAM,OAAO,GAA4B,MAAM,CAAC,WAAW,CACzD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CACzE,CAAC;IACF,IACE,CAAC,MAAM,CAAC,GAAG;QACX,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QACpB,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAEnC,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;IACJ,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,eAAe,CAAC;YAC/B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,IAAI,CAAC;YACH,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,uBAAuB,EAAE,CAAC;gBAC7D,OAAO,CAAC,GAAG,CAAC;oBACV,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,GAAG,KAAK,KAAK,QAAQ,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;wBAC5D,QAAQ,CAAC;YACb,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAsB,CAAC,CAAC;IACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,MAAM,CAAC,KAAK,CAAC,MAAM,aAAa,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,MAAM,CAAC,GAAG,IAAI,CACnH,CAAC;AACJ,CAAC","sourcesContent":["import { resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { initializationQuestions } from \"./main.constants.ts\";\nimport type { CliInvocation } from \"./main.types.ts\";\nimport { initialize } from \"./scaffold.ts\";\nimport type { InitOptions } from \"./scaffold.types.ts\";\n\nexport async function initializeCommand({\n values,\n}: CliInvocation): Promise<void> {\n const options: Record<string, unknown> = Object.fromEntries(\n Object.entries(values).filter(([key]) => ![\"help\", \"yes\"].includes(key)),\n );\n if (\n !values.yes &&\n !process.stdin.isTTY &&\n (!values.agent || !values.provider)\n )\n throw new Error(\n \"Headless initialization requires --yes for defaults, or --agent and --provider.\",\n );\n if (!values.yes && process.stdin.isTTY) {\n const terminal = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n for (const [key, label, fallback] of initializationQuestions) {\n options[key] ??=\n (await terminal.question(`${label} [${fallback}]: `)).trim() ||\n fallback;\n }\n } finally {\n terminal.close();\n }\n }\n const result = await initialize(options as InitOptions);\n process.stdout.write(\n `Initialized ${result.files.length} files in ${resolve(values.directory ?? process.cwd())}.\\nRun: ${result.run}\\n`,\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const help = "Outpost \u2014 sandboxed coding agents and workflows\n\noutpost init [--yes] [--agent codex|claude] [--provider docker|podman|vercel|daytona|local]\n [--
|
|
1
|
+
export declare const help = "Outpost \u2014 sandboxed coding agents and workflows\n\noutpost init [--yes] [--agent codex|claude] [--provider docker|podman|vercel|daytona|local]\n [--manager npm|pnpm|yarn|bun] [--model NAME] [--install] [--build] [--image NAME] [--directory PATH] [--repository PATH]\noutpost image build|remove [--engine docker|podman] [--file PATH] [--image NAME] [--uid ID] [--gid ID]\n\nNode.js 24+ and Git are required. Run generated scripts with Node.js.\nInitialization writes run.ts and project files directly into --directory (default: current directory).\n--repository selects the target Git repository; relative paths are resolved from the workflow directory.\n";
|
|
2
2
|
export declare const cliOptions: {
|
|
3
3
|
readonly help: {
|
|
4
4
|
readonly type: "boolean";
|
|
@@ -20,22 +20,16 @@ export declare const cliOptions: {
|
|
|
20
20
|
readonly provider: {
|
|
21
21
|
readonly type: "string";
|
|
22
22
|
};
|
|
23
|
-
readonly template: {
|
|
24
|
-
readonly type: "string";
|
|
25
|
-
};
|
|
26
|
-
readonly tracker: {
|
|
27
|
-
readonly type: "string";
|
|
28
|
-
};
|
|
29
23
|
readonly manager: {
|
|
30
24
|
readonly type: "string";
|
|
31
25
|
};
|
|
32
26
|
readonly model: {
|
|
33
27
|
readonly type: "string";
|
|
34
28
|
};
|
|
35
|
-
readonly
|
|
29
|
+
readonly directory: {
|
|
36
30
|
readonly type: "string";
|
|
37
31
|
};
|
|
38
|
-
readonly
|
|
32
|
+
readonly repository: {
|
|
39
33
|
readonly type: "string";
|
|
40
34
|
};
|
|
41
35
|
readonly engine: {
|
|
@@ -54,4 +48,4 @@ export declare const cliOptions: {
|
|
|
54
48
|
readonly type: "string";
|
|
55
49
|
};
|
|
56
50
|
};
|
|
57
|
-
export declare const initializationQuestions: readonly [readonly ["agent", "Agent (codex/claude)", "codex"], readonly ["provider", "Sandbox (docker/podman/vercel/daytona/local)", "docker"]
|
|
51
|
+
export declare const initializationQuestions: readonly [readonly ["agent", "Agent (codex/claude)", "codex"], readonly ["provider", "Sandbox (docker/podman/vercel/daytona/local)", "docker"]];
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export const help = `Outpost — sandboxed coding agents and workflows
|
|
2
2
|
|
|
3
3
|
outpost init [--yes] [--agent codex|claude] [--provider docker|podman|vercel|daytona|local]
|
|
4
|
-
[--
|
|
5
|
-
[--manager npm|pnpm|yarn|bun] [--model NAME] [--install] [--build] [--image NAME] [--label NAME] [--directory PATH]
|
|
4
|
+
[--manager npm|pnpm|yarn|bun] [--model NAME] [--install] [--build] [--image NAME] [--directory PATH] [--repository PATH]
|
|
6
5
|
outpost image build|remove [--engine docker|podman] [--file PATH] [--image NAME] [--uid ID] [--gid ID]
|
|
7
6
|
|
|
8
7
|
Node.js 24+ and Git are required. Run generated scripts with Node.js.
|
|
8
|
+
Initialization writes run.ts and project files directly into --directory (default: current directory).
|
|
9
|
+
--repository selects the target Git repository; relative paths are resolved from the workflow directory.
|
|
9
10
|
`;
|
|
10
11
|
export const cliOptions = {
|
|
11
12
|
help: { type: "boolean", short: "h" },
|
|
@@ -14,12 +15,10 @@ export const cliOptions = {
|
|
|
14
15
|
build: { type: "boolean" },
|
|
15
16
|
agent: { type: "string" },
|
|
16
17
|
provider: { type: "string" },
|
|
17
|
-
template: { type: "string" },
|
|
18
|
-
tracker: { type: "string" },
|
|
19
18
|
manager: { type: "string" },
|
|
20
19
|
model: { type: "string" },
|
|
21
|
-
label: { type: "string" },
|
|
22
20
|
directory: { type: "string" },
|
|
21
|
+
repository: { type: "string" },
|
|
23
22
|
engine: { type: "string" },
|
|
24
23
|
file: { type: "string" },
|
|
25
24
|
image: { type: "string" },
|
|
@@ -29,7 +28,5 @@ export const cliOptions = {
|
|
|
29
28
|
export const initializationQuestions = [
|
|
30
29
|
["agent", "Agent (codex/claude)", "codex"],
|
|
31
30
|
["provider", "Sandbox (docker/podman/vercel/daytona/local)", "docker"],
|
|
32
|
-
["template", "Template (blank/iterate/review/plan/plan-review)", "blank"],
|
|
33
|
-
["tracker", "Issue tracker (github/beads/custom)", "github"],
|
|
34
31
|
];
|
|
35
32
|
//# sourceMappingURL=main.constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.constants.js","sourceRoot":"","sources":["../../src/cli/main.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG
|
|
1
|
+
{"version":3,"file":"main.constants.js","sourceRoot":"","sources":["../../src/cli/main.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;CASnB,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;IACrC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;IACpC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;IAC5B,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;IAC1B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC5B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACzB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC7B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC9B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACxB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACzB,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IACvB,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;CACf,CAAC;AAEX,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,CAAC,OAAO,EAAE,sBAAsB,EAAE,OAAO,CAAC;IAC1C,CAAC,UAAU,EAAE,8CAA8C,EAAE,QAAQ,CAAC;CAC9D,CAAC","sourcesContent":["export const help = `Outpost — sandboxed coding agents and workflows\n\noutpost init [--yes] [--agent codex|claude] [--provider docker|podman|vercel|daytona|local]\n [--manager npm|pnpm|yarn|bun] [--model NAME] [--install] [--build] [--image NAME] [--directory PATH] [--repository PATH]\noutpost image build|remove [--engine docker|podman] [--file PATH] [--image NAME] [--uid ID] [--gid ID]\n\nNode.js 24+ and Git are required. Run generated scripts with Node.js.\nInitialization writes run.ts and project files directly into --directory (default: current directory).\n--repository selects the target Git repository; relative paths are resolved from the workflow directory.\n`;\n\nexport const cliOptions = {\n help: { type: \"boolean\", short: \"h\" },\n yes: { type: \"boolean\", short: \"y\" },\n install: { type: \"boolean\" },\n build: { type: \"boolean\" },\n agent: { type: \"string\" },\n provider: { type: \"string\" },\n manager: { type: \"string\" },\n model: { type: \"string\" },\n directory: { type: \"string\" },\n repository: { type: \"string\" },\n engine: { type: \"string\" },\n file: { type: \"string\" },\n image: { type: \"string\" },\n uid: { type: \"string\" },\n gid: { type: \"string\" },\n} as const;\n\nexport const initializationQuestions = [\n [\"agent\", \"Agent (codex/claude)\", \"codex\"],\n [\"provider\", \"Sandbox (docker/podman/vercel/daytona/local)\", \"docker\"],\n] as const;\n"]}
|
|
@@ -4,17 +4,19 @@ import { invariant } from "../domain/errors.js";
|
|
|
4
4
|
import { managerLocks, supportedManagers } from "./scaffold.constants.js";
|
|
5
5
|
export async function projectSettings(root, options) {
|
|
6
6
|
let pkg = {};
|
|
7
|
+
let hasPackage = true;
|
|
7
8
|
try {
|
|
8
9
|
pkg = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
|
|
9
10
|
if (!pkg || typeof pkg !== "object")
|
|
10
11
|
pkg = {};
|
|
11
12
|
}
|
|
12
13
|
catch (cause) {
|
|
14
|
+
if (cause.code === "ENOENT")
|
|
15
|
+
hasPackage = false;
|
|
13
16
|
if (!(cause instanceof SyntaxError) &&
|
|
14
17
|
cause.code !== "ENOENT")
|
|
15
18
|
throw cause;
|
|
16
19
|
}
|
|
17
|
-
const extension = pkg.type === "module" ? "ts" : "mts";
|
|
18
20
|
let detected = typeof pkg.packageManager === "string"
|
|
19
21
|
? pkg.packageManager.split("@")[0]
|
|
20
22
|
: undefined;
|
|
@@ -31,6 +33,10 @@ export async function projectSettings(root, options) {
|
|
|
31
33
|
}
|
|
32
34
|
const manager = options.manager ?? detected ?? "npm";
|
|
33
35
|
invariant(supportedManagers.includes(manager), "Unknown package manager");
|
|
34
|
-
return {
|
|
36
|
+
return {
|
|
37
|
+
hasPackage,
|
|
38
|
+
manager,
|
|
39
|
+
extension: pkg.type === "commonjs" ? "mts" : "ts",
|
|
40
|
+
};
|
|
35
41
|
}
|
|
36
42
|
//# sourceMappingURL=project-settings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-settings.js","sourceRoot":"","sources":["../../src/cli/project-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAO1E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,OAAoB;IAEpB,IAAI,GAAG,GAAoB,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,GAAG,GAAG,EAAE,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC;YAC9B,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAElD,MAAM,KAAK,CAAC;IAChB,CAAC;IACD,
|
|
1
|
+
{"version":3,"file":"project-settings.js","sourceRoot":"","sources":["../../src/cli/project-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAO1E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,OAAoB;IAEpB,IAAI,GAAG,GAAoB,EAAE,CAAC;IAC9B,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,GAAG,GAAG,EAAE,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,UAAU,GAAG,KAAK,CAAC;QAC3E,IACE,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC;YAC9B,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAElD,MAAM,KAAK,CAAC;IAChB,CAAC;IACD,IAAI,QAAQ,GACV,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ;QACpC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,CAAC,QAAQ,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,QAAQ,GAAG,SAAS,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,YAAY,EAAE,CAAC;YAC3C,IACE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAK,CAAC,CAAC;iBAC5B,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;iBAChB,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,EACrB,CAAC;gBACD,QAAQ,GAAG,OAAO,CAAC;gBACnB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,IAAI,KAAK,CAAC;IACrD,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,yBAAyB,CAAC,CAAC;IAE1E,OAAO;QACL,UAAU;QACV,OAAO;QACP,SAAS,EAAE,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;KAClD,CAAC;AACJ,CAAC","sourcesContent":["import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { invariant } from \"../domain/errors.ts\";\nimport { managerLocks, supportedManagers } from \"./scaffold.constants.ts\";\nimport type {\n InitOptions,\n PackageManifest,\n ProjectSettings,\n} from \"./scaffold.types.ts\";\n\nexport async function projectSettings(\n root: string,\n options: InitOptions,\n): Promise<ProjectSettings> {\n let pkg: PackageManifest = {};\n let hasPackage = true;\n try {\n pkg = JSON.parse(await readFile(join(root, \"package.json\"), \"utf8\"));\n if (!pkg || typeof pkg !== \"object\") pkg = {};\n } catch (cause) {\n if ((cause as NodeJS.ErrnoException).code === \"ENOENT\") hasPackage = false;\n if (\n !(cause instanceof SyntaxError) &&\n (cause as NodeJS.ErrnoException).code !== \"ENOENT\"\n )\n throw cause;\n }\n let detected =\n typeof pkg.packageManager === \"string\"\n ? pkg.packageManager.split(\"@\")[0]\n : undefined;\n if (!detected || !supportedManagers.includes(detected)) {\n detected = undefined;\n for (const [file, manager] of managerLocks) {\n if (\n await access(join(root, file!))\n .then(() => true)\n .catch(() => false)\n ) {\n detected = manager;\n break;\n }\n }\n }\n const manager = options.manager ?? detected ?? \"npm\";\n invariant(supportedManagers.includes(manager), \"Unknown package manager\");\n\n return {\n hasPackage,\n manager,\n extension: pkg.type === \"commonjs\" ? \"mts\" : \"ts\",\n };\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { InitOptions } from "./scaffold.types.ts";
|
|
2
|
-
export declare function scaffoldFiles(options: InitOptions, extension:
|
|
2
|
+
export declare function scaffoldFiles(options: InitOptions, hasPackage: boolean, extension: "ts" | "mts"): Promise<Record<string, string>>;
|
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { imageRecipe, providerPackages } from "./scaffold.constants.js";
|
|
3
|
+
import { starter } from "./starters.js";
|
|
4
|
+
export async function scaffoldFiles(options, hasPackage, extension) {
|
|
5
|
+
const agent = options.agent ?? "codex", provider = options.provider ?? "docker";
|
|
5
6
|
const files = {
|
|
6
|
-
[`run.${extension}`]: starter(options
|
|
7
|
+
[`run.${extension}`]: starter(options),
|
|
7
8
|
"brief.md": "Objective: {{OBJECTIVE}}\n\nWork on {{WORK_BRANCH}} from {{BASE_BRANCH}}. Inspect the repository, implement the objective, run relevant tests and commit your changes. When finished, write <outpost>done</outpost>.\n",
|
|
8
|
-
".env.example":
|
|
9
|
-
|
|
10
|
-
".gitignore": ".env\nworkspaces/\nlocks/\nrecovery/\nlogs/\n",
|
|
9
|
+
".env.example": agent === "codex" ? "OPENAI_API_KEY=\n" : "ANTHROPIC_API_KEY=\n",
|
|
10
|
+
".gitignore": "node_modules/\n.env\n.outpost/workspaces/\n.outpost/locks/\n.outpost/recovery/\n.outpost/logs/\n",
|
|
11
11
|
};
|
|
12
12
|
if (provider === "docker" || provider === "podman")
|
|
13
|
-
files[provider === "docker" ? "Dockerfile" : "Containerfile"] =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
files[provider === "docker" ? "Dockerfile" : "Containerfile"] = imageRecipe;
|
|
14
|
+
if (!hasPackage) {
|
|
15
|
+
const manifest = JSON.parse(await readFile(new URL("../../package.json", import.meta.url), "utf8"));
|
|
16
|
+
files["package.json"] =
|
|
17
|
+
JSON.stringify({
|
|
18
|
+
private: true,
|
|
19
|
+
type: "module",
|
|
20
|
+
scripts: { start: `node run.${extension}` },
|
|
21
|
+
engines: { node: ">=24" },
|
|
22
|
+
devDependencies: {
|
|
23
|
+
"@elie-laloum/outpost": `^${manifest.version}`,
|
|
24
|
+
...Object.fromEntries(providerPackages[provider].map((name) => [
|
|
25
|
+
name,
|
|
26
|
+
manifest.peerDependencies[name],
|
|
27
|
+
])),
|
|
28
|
+
},
|
|
29
|
+
}, null, 2) + "\n";
|
|
30
|
+
}
|
|
25
31
|
return files;
|
|
26
32
|
}
|
|
27
33
|
//# sourceMappingURL=scaffold-files.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold-files.js","sourceRoot":"","sources":["../../src/cli/scaffold-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scaffold-files.js","sourceRoot":"","sources":["../../src/cli/scaffold-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAoB,EACpB,UAAmB,EACnB,SAAuB;IAEvB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,EACpC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAC1C,MAAM,KAAK,GAA2B;QACpC,CAAC,OAAO,SAAS,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;QACtC,UAAU,EACR,wNAAwN;QAC1N,cAAc,EACZ,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,sBAAsB;QAClE,YAAY,EACV,kGAAkG;KACrG,CAAC;IACF,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ;QAChD,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,WAAW,CAAC;IAE9E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CACvE,CAAC;QACF,KAAK,CAAC,cAAc,CAAC;YACnB,IAAI,CAAC,SAAS,CACZ;gBACE,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,SAAS,EAAE,EAAE;gBAC3C,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;gBACzB,eAAe,EAAE;oBACf,sBAAsB,EAAE,IAAI,QAAQ,CAAC,OAAO,EAAE;oBAC9C,GAAG,MAAM,CAAC,WAAW,CACnB,gBAAgB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;wBACvC,IAAI;wBACJ,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC;qBAChC,CAAC,CACH;iBACF;aACF,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { imageRecipe, providerPackages } from \"./scaffold.constants.ts\";\nimport type { InitOptions } from \"./scaffold.types.ts\";\nimport { starter } from \"./starters.ts\";\n\nexport async function scaffoldFiles(\n options: InitOptions,\n hasPackage: boolean,\n extension: \"ts\" | \"mts\",\n): Promise<Record<string, string>> {\n const agent = options.agent ?? \"codex\",\n provider = options.provider ?? \"docker\";\n const files: Record<string, string> = {\n [`run.${extension}`]: starter(options),\n \"brief.md\":\n \"Objective: {{OBJECTIVE}}\\n\\nWork on {{WORK_BRANCH}} from {{BASE_BRANCH}}. Inspect the repository, implement the objective, run relevant tests and commit your changes. When finished, write <outpost>done</outpost>.\\n\",\n \".env.example\":\n agent === \"codex\" ? \"OPENAI_API_KEY=\\n\" : \"ANTHROPIC_API_KEY=\\n\",\n \".gitignore\":\n \"node_modules/\\n.env\\n.outpost/workspaces/\\n.outpost/locks/\\n.outpost/recovery/\\n.outpost/logs/\\n\",\n };\n if (provider === \"docker\" || provider === \"podman\")\n files[provider === \"docker\" ? \"Dockerfile\" : \"Containerfile\"] = imageRecipe;\n\n if (!hasPackage) {\n const manifest = JSON.parse(\n await readFile(new URL(\"../../package.json\", import.meta.url), \"utf8\"),\n );\n files[\"package.json\"] =\n JSON.stringify(\n {\n private: true,\n type: \"module\",\n scripts: { start: `node run.${extension}` },\n engines: { node: \">=24\" },\n devDependencies: {\n \"@elie-laloum/outpost\": `^${manifest.version}`,\n ...Object.fromEntries(\n providerPackages[provider].map((name) => [\n name,\n manifest.peerDependencies[name],\n ]),\n ),\n },\n },\n null,\n 2,\n ) + \"\\n\";\n }\n return files;\n}\n"]}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { invariant } from "../domain/errors.js";
|
|
2
|
-
import { supportedAgents, supportedProviders
|
|
2
|
+
import { supportedAgents, supportedProviders } from "./scaffold.constants.js";
|
|
3
3
|
export function validateInitialization(options) {
|
|
4
|
-
const agent = options.agent ?? "codex", provider = options.provider ?? "docker"
|
|
4
|
+
const agent = options.agent ?? "codex", provider = options.provider ?? "docker";
|
|
5
5
|
invariant(supportedAgents.includes(agent), "Choose codex or claude");
|
|
6
6
|
invariant(supportedProviders.includes(provider), "Unknown sandbox provider");
|
|
7
|
-
invariant(supportedTemplates.includes(template), "Unknown starter template");
|
|
8
|
-
if (options.tracker)
|
|
9
|
-
invariant(supportedTrackers.includes(options.tracker), "Unknown tracker");
|
|
10
7
|
}
|
|
11
8
|
//# sourceMappingURL=scaffold-validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold-validation.js","sourceRoot":"","sources":["../../src/cli/scaffold-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"scaffold-validation.js","sourceRoot":"","sources":["../../src/cli/scaffold-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG9E,MAAM,UAAU,sBAAsB,CAAC,OAAoB;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,EACpC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAC1C,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,wBAAwB,CAAC,CAAC;IACrE,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,0BAA0B,CAAC,CAAC;AAC/E,CAAC","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport { supportedAgents, supportedProviders } from \"./scaffold.constants.ts\";\nimport type { InitOptions } from \"./scaffold.types.ts\";\n\nexport function validateInitialization(options: InitOptions): void {\n const agent = options.agent ?? \"codex\",\n provider = options.provider ?? \"docker\";\n invariant(supportedAgents.includes(agent), \"Choose codex or claude\");\n invariant(supportedProviders.includes(provider), \"Unknown sandbox provider\");\n}\n"]}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export declare const imageRecipe: string;
|
|
2
2
|
export declare const supportedAgents: readonly string[];
|
|
3
3
|
export declare const supportedProviders: readonly string[];
|
|
4
|
-
export declare const supportedTemplates: readonly string[];
|
|
5
|
-
export declare const supportedTrackers: readonly string[];
|
|
6
4
|
export declare const supportedManagers: readonly string[];
|
|
7
5
|
export declare const managerLocks: readonly [readonly ["pnpm-lock.yaml", "pnpm"], readonly ["yarn.lock", "yarn"], readonly ["bun.lock", "bun"], readonly ["bun.lockb", "bun"]];
|
|
8
6
|
export declare const providerPackages: {
|
|
@@ -2,9 +2,10 @@ import { agentVersions } from "../providers/versions.js";
|
|
|
2
2
|
export const imageRecipe = `FROM node:24-bookworm-slim
|
|
3
3
|
ARG AGENT_UID=1000
|
|
4
4
|
ARG AGENT_GID=1000
|
|
5
|
-
RUN apt-get update && apt-get install -y --no-install-recommends git
|
|
5
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git openssh-client ca-certificates curl procps util-linux python3 && rm -rf /var/lib/apt/lists/*
|
|
6
6
|
RUN npm install -g --allow-scripts=@anthropic-ai/claude-code @openai/codex@${agentVersions.codex} @anthropic-ai/claude-code@${agentVersions.claude}
|
|
7
7
|
RUN groupmod -o -g "$AGENT_GID" node && usermod -o -u "$AGENT_UID" -g "$AGENT_GID" node
|
|
8
|
+
RUN mkdir -p /home/agent && chown "$AGENT_UID:$AGENT_GID" /home/agent && chmod 700 /home/agent
|
|
8
9
|
ENV HOME=/home/agent
|
|
9
10
|
USER $AGENT_UID:$AGENT_GID
|
|
10
11
|
WORKDIR /workspace
|
|
@@ -17,18 +18,6 @@ export const supportedProviders = [
|
|
|
17
18
|
"daytona",
|
|
18
19
|
"local",
|
|
19
20
|
];
|
|
20
|
-
export const supportedTemplates = [
|
|
21
|
-
"blank",
|
|
22
|
-
"iterate",
|
|
23
|
-
"review",
|
|
24
|
-
"plan",
|
|
25
|
-
"plan-review",
|
|
26
|
-
];
|
|
27
|
-
export const supportedTrackers = [
|
|
28
|
-
"github",
|
|
29
|
-
"beads",
|
|
30
|
-
"custom",
|
|
31
|
-
];
|
|
32
21
|
export const supportedManagers = [
|
|
33
22
|
"npm",
|
|
34
23
|
"pnpm",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.constants.js","sourceRoot":"","sources":["../../src/cli/scaffold.constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,CAAC,MAAM,WAAW,GAAG;;;;6EAIkD,aAAa,CAAC,KAAK,8BAA8B,aAAa,CAAC,MAAM
|
|
1
|
+
{"version":3,"file":"scaffold.constants.js","sourceRoot":"","sources":["../../src/cli/scaffold.constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,CAAC,MAAM,WAAW,GAAG;;;;6EAIkD,aAAa,CAAC,KAAK,8BAA8B,aAAa,CAAC,MAAM;;;;;;CAMjJ,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAsB;IACnD,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,OAAO;CACR,CAAC;AACF,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IAClD,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;CACN,CAAC;AACF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAC1B,CAAC,WAAW,EAAE,MAAM,CAAC;IACrB,CAAC,UAAU,EAAE,KAAK,CAAC;IACnB,CAAC,WAAW,EAAE,KAAK,CAAC;CACZ,CAAC;AACX,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,CAAC,iBAAiB,CAAC;IAC3B,OAAO,EAAE,CAAC,cAAc,CAAC;CACjB,CAAC","sourcesContent":["import { agentVersions } from \"../providers/versions.ts\";\n\nexport const imageRecipe = `FROM node:24-bookworm-slim\nARG AGENT_UID=1000\nARG AGENT_GID=1000\nRUN apt-get update && apt-get install -y --no-install-recommends git openssh-client ca-certificates curl procps util-linux python3 && rm -rf /var/lib/apt/lists/*\nRUN npm install -g --allow-scripts=@anthropic-ai/claude-code @openai/codex@${agentVersions.codex} @anthropic-ai/claude-code@${agentVersions.claude}\nRUN groupmod -o -g \"$AGENT_GID\" node && usermod -o -u \"$AGENT_UID\" -g \"$AGENT_GID\" node\nRUN mkdir -p /home/agent && chown \"$AGENT_UID:$AGENT_GID\" /home/agent && chmod 700 /home/agent\nENV HOME=/home/agent\nUSER $AGENT_UID:$AGENT_GID\nWORKDIR /workspace\n`;\n\nexport const supportedAgents: readonly string[] = [\"codex\", \"claude\"];\nexport const supportedProviders: readonly string[] = [\n \"docker\",\n \"podman\",\n \"vercel\",\n \"daytona\",\n \"local\",\n];\nexport const supportedManagers: readonly string[] = [\n \"npm\",\n \"pnpm\",\n \"yarn\",\n \"bun\",\n];\nexport const managerLocks = [\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"bun.lock\", \"bun\"],\n [\"bun.lockb\", \"bun\"],\n] as const;\nexport const providerPackages = {\n docker: [],\n podman: [],\n local: [],\n vercel: [\"@vercel/sandbox\"],\n daytona: [\"@daytona/sdk\"],\n} as const;\n"]}
|
package/dist/cli/scaffold.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ import type { Executor } from "../infrastructure/process.types.ts";
|
|
|
2
2
|
import type { InitOptions, ScaffoldResult } from "./scaffold.types.ts";
|
|
3
3
|
export { manageImage } from "./image.ts";
|
|
4
4
|
export { imageRecipe } from "./scaffold.constants.ts";
|
|
5
|
-
export type { InitOptions
|
|
5
|
+
export type { InitOptions } from "./scaffold.types.ts";
|
|
6
6
|
export declare function initialize(options?: InitOptions, executor?: Executor): Promise<ScaffoldResult>;
|
package/dist/cli/scaffold.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { appendFile, lstat, mkdir, readFile, writeFile, } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { OutpostError } from "../domain/errors.js";
|
|
4
4
|
import { requireSuccess } from "../infrastructure/process.js";
|
|
5
|
+
import { imageName } from "../providers/container.js";
|
|
5
6
|
import { manageImage } from "./image.js";
|
|
6
7
|
import { projectSettings } from "./project-settings.js";
|
|
7
8
|
import { scaffoldFiles } from "./scaffold-files.js";
|
|
@@ -10,19 +11,43 @@ import { providerPackages } from "./scaffold.constants.js";
|
|
|
10
11
|
export { manageImage } from "./image.js";
|
|
11
12
|
export { imageRecipe } from "./scaffold.constants.js";
|
|
12
13
|
export async function initialize(options = {}, executor) {
|
|
13
|
-
const root = resolve(options.directory ?? process.cwd())
|
|
14
|
+
const root = resolve(options.directory ?? process.cwd());
|
|
14
15
|
const provider = options.provider ?? "docker";
|
|
15
16
|
validateInitialization(options);
|
|
16
|
-
const {
|
|
17
|
-
const files = scaffoldFiles(options, extension);
|
|
17
|
+
const { hasPackage, manager, extension } = await projectSettings(root, options);
|
|
18
|
+
const files = await scaffoldFiles({ ...options, image: options.image ?? imageName(root) }, hasPackage, extension);
|
|
19
|
+
const existingIgnore = await readFile(join(root, ".gitignore"), "utf8").catch((error) => {
|
|
20
|
+
if (error.code === "ENOENT")
|
|
21
|
+
return undefined;
|
|
22
|
+
throw error;
|
|
23
|
+
});
|
|
24
|
+
const ignore = files[".gitignore"];
|
|
25
|
+
if (existingIgnore !== undefined)
|
|
26
|
+
delete files[".gitignore"];
|
|
18
27
|
for (const name of Object.keys(files))
|
|
19
|
-
if (await
|
|
28
|
+
if (await lstat(join(root, name))
|
|
20
29
|
.then(() => true)
|
|
21
|
-
.catch(() =>
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
.catch((error) => {
|
|
31
|
+
if (error.code === "ENOENT")
|
|
32
|
+
return false;
|
|
33
|
+
throw error;
|
|
34
|
+
}))
|
|
35
|
+
throw new OutpostError("configuration", `Initialization would overwrite ${name}`);
|
|
36
|
+
await mkdir(root, { recursive: true });
|
|
24
37
|
for (const [name, content] of Object.entries(files))
|
|
25
|
-
await writeFile(join(
|
|
38
|
+
await writeFile(join(root, name), content, { flag: "wx" });
|
|
39
|
+
if (existingIgnore !== undefined) {
|
|
40
|
+
const rules = new Set(existingIgnore.split(/\r?\n/));
|
|
41
|
+
const additions = ignore
|
|
42
|
+
.trimEnd()
|
|
43
|
+
.split("\n")
|
|
44
|
+
.filter((rule) => !rules.has(rule));
|
|
45
|
+
if (additions.length) {
|
|
46
|
+
const suffix = `${existingIgnore && !existingIgnore.endsWith("\n") ? "\n" : ""}${additions.join("\n")}\n`;
|
|
47
|
+
await appendFile(join(root, ".gitignore"), suffix);
|
|
48
|
+
files[".gitignore"] = existingIgnore + suffix;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
26
51
|
if (options.install) {
|
|
27
52
|
const packages = ["@elie-laloum/outpost", ...providerPackages[provider]];
|
|
28
53
|
const args = manager === "npm"
|
|
@@ -36,23 +61,6 @@ export async function initialize(options = {}, executor) {
|
|
|
36
61
|
}
|
|
37
62
|
: { executable: manager, arguments: args, directory: root }, executor);
|
|
38
63
|
}
|
|
39
|
-
if (options.label) {
|
|
40
|
-
invariant(options.tracker === "github", "Labels require the GitHub tracker");
|
|
41
|
-
await requireSuccess({
|
|
42
|
-
executable: "gh",
|
|
43
|
-
arguments: [
|
|
44
|
-
"label",
|
|
45
|
-
"create",
|
|
46
|
-
options.label,
|
|
47
|
-
"--color",
|
|
48
|
-
"4969ED",
|
|
49
|
-
"--description",
|
|
50
|
-
"Ready for Outpost",
|
|
51
|
-
"--force",
|
|
52
|
-
],
|
|
53
|
-
directory: root,
|
|
54
|
-
}, executor);
|
|
55
|
-
}
|
|
56
64
|
if (options.build && (provider === "docker" || provider === "podman"))
|
|
57
65
|
await manageImage("build", {
|
|
58
66
|
directory: root,
|
|
@@ -60,8 +68,8 @@ export async function initialize(options = {}, executor) {
|
|
|
60
68
|
...(options.image ? { image: options.image } : {}),
|
|
61
69
|
}, executor);
|
|
62
70
|
return {
|
|
63
|
-
files: Object.keys(files).map((name) => join(
|
|
64
|
-
run: `node
|
|
71
|
+
files: Object.keys(files).map((name) => join(root, name)),
|
|
72
|
+
run: `node run.${extension}`,
|
|
65
73
|
};
|
|
66
74
|
}
|
|
67
75
|
//# sourceMappingURL=scaffold.js.map
|