@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/dist/cli/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/cli/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/cli/scaffold.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n appendFile,\n lstat,\n mkdir,\n readFile,\n writeFile,\n} from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { OutpostError } 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 { manageImage } from \"./image.ts\";\nimport { projectSettings } from \"./project-settings.ts\";\nimport { scaffoldFiles } from \"./scaffold-files.ts\";\nimport { validateInitialization } from \"./scaffold-validation.ts\";\nimport { providerPackages } from \"./scaffold.constants.ts\";\nimport type { InitOptions, ScaffoldResult } from \"./scaffold.types.ts\";\n\nexport { manageImage } from \"./image.ts\";\nexport { imageRecipe } from \"./scaffold.constants.ts\";\nexport type { InitOptions } from \"./scaffold.types.ts\";\n\nexport async function initialize(\n options: InitOptions = {},\n executor?: Executor,\n): Promise<ScaffoldResult> {\n const root = resolve(options.directory ?? process.cwd());\n const provider = options.provider ?? \"docker\";\n validateInitialization(options);\n const { hasPackage, manager, extension } = await projectSettings(\n root,\n options,\n );\n const files = await scaffoldFiles(\n { ...options, image: options.image ?? imageName(root) },\n hasPackage,\n extension,\n );\n const existingIgnore = await readFile(join(root, \".gitignore\"), \"utf8\").catch(\n (error) => {\n if (error.code === \"ENOENT\") return undefined;\n throw error;\n },\n );\n const ignore = files[\".gitignore\"]!;\n if (existingIgnore !== undefined) delete files[\".gitignore\"];\n for (const name of Object.keys(files))\n if (\n await lstat(join(root, name))\n .then(() => true)\n .catch((error) => {\n if (error.code === \"ENOENT\") return false;\n throw error;\n })\n )\n throw new OutpostError(\n \"configuration\",\n `Initialization would overwrite ${name}`,\n );\n await mkdir(root, { recursive: true });\n for (const [name, content] of Object.entries(files))\n await writeFile(join(root, name), content, { flag: \"wx\" });\n if (existingIgnore !== undefined) {\n const rules = new Set(existingIgnore.split(/\\r?\\n/));\n const additions = ignore\n .trimEnd()\n .split(\"\\n\")\n .filter((rule) => !rules.has(rule));\n if (additions.length) {\n const suffix = `${existingIgnore && !existingIgnore.endsWith(\"\\n\") ? \"\\n\" : \"\"}${additions.join(\"\\n\")}\\n`;\n await appendFile(join(root, \".gitignore\"), suffix);\n files[\".gitignore\"] = existingIgnore + suffix;\n }\n }\n if (options.install) {\n const packages = [\"@elie-laloum/outpost\", ...providerPackages[provider]];\n const args =\n manager === \"npm\"\n ? [\"install\", \"--save-dev\", ...packages]\n : [\"add\", \"--dev\", ...packages];\n await requireSuccess(\n process.platform === \"win32\"\n ? {\n executable: \"cmd.exe\",\n arguments: [\"/d\", \"/c\", [manager, ...args].join(\" \")],\n directory: root,\n }\n : { executable: manager, arguments: args, directory: root },\n executor,\n );\n }\n if (options.build && (provider === \"docker\" || provider === \"podman\"))\n await manageImage(\n \"build\",\n {\n directory: root,\n engine: provider,\n ...(options.image ? { image: options.image } : {}),\n },\n executor,\n );\n return {\n files: Object.keys(files).map((name) => join(root, name)),\n run: `node run.${extension}`,\n };\n}\n"]}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
export type Template = "blank" | "iterate" | "review" | "plan" | "plan-review";
|
|
2
1
|
export interface InitOptions {
|
|
3
2
|
readonly directory?: string;
|
|
3
|
+
readonly repository?: string;
|
|
4
4
|
readonly agent?: "claude" | "codex";
|
|
5
5
|
readonly provider?: "docker" | "podman" | "vercel" | "daytona" | "local";
|
|
6
|
-
readonly template?: Template;
|
|
7
|
-
readonly tracker?: "github" | "beads" | "custom";
|
|
8
6
|
readonly manager?: "npm" | "pnpm" | "yarn" | "bun";
|
|
9
7
|
readonly model?: string;
|
|
10
8
|
readonly install?: boolean;
|
|
11
|
-
readonly label?: string;
|
|
12
9
|
readonly build?: boolean;
|
|
13
10
|
readonly image?: string;
|
|
14
11
|
}
|
|
@@ -17,7 +14,8 @@ export interface PackageManifest {
|
|
|
17
14
|
readonly packageManager?: string;
|
|
18
15
|
}
|
|
19
16
|
export interface ProjectSettings {
|
|
20
|
-
readonly extension:
|
|
17
|
+
readonly extension: "ts" | "mts";
|
|
18
|
+
readonly hasPackage: boolean;
|
|
21
19
|
readonly manager: string;
|
|
22
20
|
}
|
|
23
21
|
export interface ScaffoldResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.types.js","sourceRoot":"","sources":["../../src/cli/scaffold.types.ts"],"names":[],"mappings":"","sourcesContent":["export
|
|
1
|
+
{"version":3,"file":"scaffold.types.js","sourceRoot":"","sources":["../../src/cli/scaffold.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface InitOptions {\n readonly directory?: string;\n readonly repository?: string;\n readonly agent?: \"claude\" | \"codex\";\n readonly provider?: \"docker\" | \"podman\" | \"vercel\" | \"daytona\" | \"local\";\n readonly manager?: \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n readonly model?: string;\n readonly install?: boolean;\n readonly build?: boolean;\n readonly image?: string;\n}\n\nexport interface PackageManifest {\n readonly type?: string;\n readonly packageManager?: string;\n}\nexport interface ProjectSettings {\n readonly extension: \"ts\" | \"mts\";\n readonly hasPackage: boolean;\n readonly manager: string;\n}\nexport interface ScaffoldResult {\n files: readonly string[];\n run: string;\n}\n"]}
|
package/dist/cli/starters.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import type { InitOptions } from "./scaffold.types.ts";
|
|
2
|
-
export declare function starter(options: InitOptions
|
|
3
|
-
export declare function tracker(kind: NonNullable<InitOptions["tracker"]>, label?: string): string;
|
|
2
|
+
export declare function starter(options: InitOptions): string;
|
package/dist/cli/starters.js
CHANGED
|
@@ -1,34 +1,46 @@
|
|
|
1
|
-
export function starter(options
|
|
2
|
-
const agent = options.agent ?? "codex", provider = options.provider ?? "docker"
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return reply;
|
|
26
|
-
}
|
|
27
|
-
export const backlog: Backlog = {
|
|
28
|
-
async list(signal) { return await (await request("issues?state=open", "GET", signal)).json() as Issue[]; },
|
|
29
|
-
async get(id, signal) { return await (await request("issues/" + encodeURIComponent(id), "GET", signal)).json() as Issue; },
|
|
30
|
-
async close(id, signal) { await request("issues/" + encodeURIComponent(id) + "/close", "POST", signal); },
|
|
1
|
+
export function starter(options) {
|
|
2
|
+
const agent = options.agent ?? "codex", provider = options.provider ?? "docker";
|
|
3
|
+
const model = options.model ? `model: ${JSON.stringify(options.model)}` : "";
|
|
4
|
+
const image = options.image && (provider === "docker" || provider === "podman")
|
|
5
|
+
? `image: ${JSON.stringify(options.image)}, `
|
|
6
|
+
: "";
|
|
7
|
+
return `import { readFile } from "node:fs/promises";
|
|
8
|
+
import { resolve } from "node:path";
|
|
9
|
+
import { parseEnv } from "node:util";
|
|
10
|
+
import { dispatch, ${agent}, OutpostError, reporter } from "@elie-laloum/outpost";
|
|
11
|
+
import { ${provider} } from "@elie-laloum/outpost/providers/${provider}";
|
|
12
|
+
|
|
13
|
+
// Paths are relative to this workflow, regardless of where Node is launched.
|
|
14
|
+
const repository = resolve(import.meta.dirname, ${JSON.stringify(options.repository ?? ".")});
|
|
15
|
+
const environment = await readFile(new URL(".env", import.meta.url), "utf8").catch((error) => {
|
|
16
|
+
if (error.code === "ENOENT") return "";
|
|
17
|
+
throw error;
|
|
18
|
+
});
|
|
19
|
+
const variables = Object.fromEntries(
|
|
20
|
+
Object.entries(parseEnv(environment)).map(([key, value]) => [key, value || process.env[key] || ""]),
|
|
21
|
+
);
|
|
22
|
+
const runtime = {
|
|
23
|
+
agent: ${agent}({ ${model} }),
|
|
24
|
+
provider: ${provider}({ ${image}variables }),
|
|
31
25
|
};
|
|
26
|
+
const objective = process.argv.slice(2).join(" ") || "Inspect this repository and implement one useful improvement.";
|
|
27
|
+
|
|
28
|
+
console.error("[outpost] Preparing sandbox...");
|
|
29
|
+
try {
|
|
30
|
+
const result = await dispatch({
|
|
31
|
+
...runtime,
|
|
32
|
+
repository,
|
|
33
|
+
branch: { mode: "integrate" },
|
|
34
|
+
brief: { file: resolve(import.meta.dirname, "brief.md"), values: { OBJECTIVE: objective } },
|
|
35
|
+
observe: reporter(),
|
|
36
|
+
warn: (message) => console.error(message),
|
|
37
|
+
});
|
|
38
|
+
console.log({ branch: result.branch, commits: result.commits, conversation: result.conversation });
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (!(error instanceof OutpostError) || error.code !== "aborted") throw error;
|
|
41
|
+
process.exitCode ||= 130;
|
|
42
|
+
console.error("[outpost] Cancelled. Recovery details:", error.recovery);
|
|
43
|
+
}
|
|
32
44
|
`;
|
|
33
45
|
}
|
|
34
46
|
//# sourceMappingURL=starters.js.map
|
package/dist/cli/starters.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starters.js","sourceRoot":"","sources":["../../src/cli/starters.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,OAAO,CAAC,OAAoB
|
|
1
|
+
{"version":3,"file":"starters.js","sourceRoot":"","sources":["../../src/cli/starters.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,OAAO,CAAC,OAAoB;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,EACpC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,MAAM,KAAK,GACT,OAAO,CAAC,KAAK,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,CAAC;QAC/D,CAAC,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI;QAC7C,CAAC,CAAC,EAAE,CAAC;IACT,OAAO;;;qBAGY,KAAK;WACf,QAAQ,2CAA2C,QAAQ;;;kDAGpB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC;;;;;;;;;WAShF,KAAK,MAAM,KAAK;cACb,QAAQ,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;CAoBhC,CAAC;AACF,CAAC","sourcesContent":["import type { InitOptions } from \"./scaffold.types.ts\";\n\nexport function starter(options: InitOptions): string {\n const agent = options.agent ?? \"codex\",\n provider = options.provider ?? \"docker\";\n const model = options.model ? `model: ${JSON.stringify(options.model)}` : \"\";\n const image =\n options.image && (provider === \"docker\" || provider === \"podman\")\n ? `image: ${JSON.stringify(options.image)}, `\n : \"\";\n return `import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { parseEnv } from \"node:util\";\nimport { dispatch, ${agent}, OutpostError, reporter } from \"@elie-laloum/outpost\";\nimport { ${provider} } from \"@elie-laloum/outpost/providers/${provider}\";\n\n// Paths are relative to this workflow, regardless of where Node is launched.\nconst repository = resolve(import.meta.dirname, ${JSON.stringify(options.repository ?? \".\")});\nconst environment = await readFile(new URL(\".env\", import.meta.url), \"utf8\").catch((error) => {\n if (error.code === \"ENOENT\") return \"\";\n throw error;\n});\nconst variables = Object.fromEntries(\n Object.entries(parseEnv(environment)).map(([key, value]) => [key, value || process.env[key] || \"\"]),\n);\nconst runtime = {\n agent: ${agent}({ ${model} }),\n provider: ${provider}({ ${image}variables }),\n};\nconst objective = process.argv.slice(2).join(\" \") || \"Inspect this repository and implement one useful improvement.\";\n\nconsole.error(\"[outpost] Preparing sandbox...\");\ntry {\n const result = await dispatch({\n ...runtime,\n repository,\n branch: { mode: \"integrate\" },\n brief: { file: resolve(import.meta.dirname, \"brief.md\"), values: { OBJECTIVE: objective } },\n observe: reporter(),\n warn: (message) => console.error(message),\n });\n console.log({ branch: result.branch, commits: result.commits, conversation: result.conversation });\n} catch (error) {\n if (!(error instanceof OutpostError) || error.code !== \"aborted\") throw error;\n process.exitCode ||= 130;\n console.error(\"[outpost] Cancelled. Recovery details:\", error.recovery);\n}\n`;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,6 @@ export type { DispatchOptions, Execution, Turn, } from "./application/execution.
|
|
|
4
4
|
export { WorkflowFailure, task, workflow } from "./domain/workflow.ts";
|
|
5
5
|
export type { Retry, Task, TaskContext, TaskOptions, TaskRecord, TaskStatus, Workflow, WorkflowEvent, WorkflowOptions, WorkflowResult, } from "./domain/workflow.ts";
|
|
6
6
|
export { agentTask, commandTask, isolatedTask } from "./application/tasks.ts";
|
|
7
|
-
export { campaign } from "./application/campaign.ts";
|
|
8
|
-
export type { CampaignEvent, CampaignOptions, CampaignResult, IssueOutcome, } from "./application/campaign.ts";
|
|
9
|
-
export type { Assignment, Backlog, Issue } from "./domain/backlog.ts";
|
|
10
|
-
export { beadsBacklog, githubBacklog } from "./providers/backlogs.ts";
|
|
11
|
-
export type { BacklogSettings } from "./providers/backlogs.ts";
|
|
12
7
|
export { claude, codex } from "./providers/agents.ts";
|
|
13
8
|
export { agentVersions } from "./providers/versions.ts";
|
|
14
9
|
export { conversations } from "./infrastructure/conversations.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export { attach, createSandbox, dispatch, openWorkspace, } from "./application/outpost.js";
|
|
2
2
|
export { WorkflowFailure, task, workflow } from "./domain/workflow.js";
|
|
3
3
|
export { agentTask, commandTask, isolatedTask } from "./application/tasks.js";
|
|
4
|
-
export { campaign } from "./application/campaign.js";
|
|
5
|
-
export { beadsBacklog, githubBacklog } from "./providers/backlogs.js";
|
|
6
4
|
export { claude, codex } from "./providers/agents.js";
|
|
7
5
|
export { agentVersions } from "./providers/versions.js";
|
|
8
6
|
export { conversations } from "./infrastructure/conversations.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,QAAQ,EACR,aAAa,GACd,MAAM,0BAA0B,CAAC;AAoBlC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAevE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,QAAQ,EACR,aAAa,GACd,MAAM,0BAA0B,CAAC;AAoBlC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAevE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AASlE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE3E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAI/D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAkCnE,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["export {\n attach,\n createSandbox,\n dispatch,\n openWorkspace,\n} from \"./application/outpost.ts\";\n\nexport type {\n AttachOptions,\n AttachResult,\n ContinuationOptions,\n DispatchResult,\n Sandbox,\n SandboxOptions,\n WarmDispatchResult,\n Workspace,\n WorkspaceOptions,\n} from \"./application/outpost.ts\";\n\nexport type {\n DispatchOptions,\n Execution,\n Turn,\n} from \"./application/execution.ts\";\n\nexport { WorkflowFailure, task, workflow } from \"./domain/workflow.ts\";\n\nexport type {\n Retry,\n Task,\n TaskContext,\n TaskOptions,\n TaskRecord,\n TaskStatus,\n Workflow,\n WorkflowEvent,\n WorkflowOptions,\n WorkflowResult,\n} from \"./domain/workflow.ts\";\n\nexport { agentTask, commandTask, isolatedTask } from \"./application/tasks.ts\";\n\nexport { claude, codex } from \"./providers/agents.ts\";\n\nexport { agentVersions } from \"./providers/versions.ts\";\n\nexport { conversations } from \"./infrastructure/conversations.ts\";\n\nexport type {\n ConversationFormat,\n ConversationLocation,\n} from \"./infrastructure/conversations.ts\";\n\nexport type { ClaudeSettings, CodexSettings } from \"./providers/agents.ts\";\n\nexport { mountedProvider, remoteProvider } from \"./providers/factories.ts\";\n\nexport { ResponseError, response } from \"./domain/response.ts\";\n\nexport type { ResponseSpec, StandardValidator } from \"./domain/response.ts\";\n\nexport { OutpostError, recoveryDetails } from \"./domain/errors.ts\";\n\nexport type { FaultCode } from \"./domain/errors.ts\";\n\nexport type {\n AgentAdapter,\n AgentEvent,\n AgentInput,\n AgentObservation,\n BranchPolicy,\n Channel,\n Command,\n CommandResult,\n Commit,\n ConversationContext,\n ConversationRecord,\n ConversationStore,\n Disposal,\n LifecycleHooks,\n SandboxContext,\n SandboxLease,\n SandboxProvider,\n StageLimits,\n TransferOptions,\n Usage,\n Variables,\n Volume,\n WorkspaceRecord,\n} from \"./domain/ports.ts\";\n\nexport type { Brief, PromptVariables } from \"./domain/prompts.ts\";\n\nexport type { Logging } from \"./infrastructure/journal.ts\";\n\nexport { reporter } from \"./infrastructure/reporter.ts\";\n\nexport type { ReporterOptions } from \"./infrastructure/reporter.ts\";\n\nexport type { VariableQuestion } from \"./application/interactive-brief.ts\";\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { pipeline } from "node:stream/promises";
|
|
3
|
+
import { OutpostError } from "../domain/errors.js";
|
|
4
|
+
import { processDefaults } from "./process.constants.js";
|
|
5
|
+
import { transfer } from "./transfer.js";
|
|
6
|
+
export function binaryExecutor(streams) {
|
|
7
|
+
return (command) => transfer(command, async (signal) => {
|
|
8
|
+
signal.throwIfAborted();
|
|
9
|
+
const child = spawn(command.executable, [...(command.arguments ?? [])], {
|
|
10
|
+
cwd: command.directory,
|
|
11
|
+
env: { ...process.env, ...command.variables },
|
|
12
|
+
windowsHide: true,
|
|
13
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
14
|
+
signal,
|
|
15
|
+
killSignal: "SIGKILL",
|
|
16
|
+
});
|
|
17
|
+
let stderr = "";
|
|
18
|
+
child.stderr.on("data", (data) => {
|
|
19
|
+
stderr = (stderr + data.toString("utf8")).slice(-processDefaults.retainBytes);
|
|
20
|
+
});
|
|
21
|
+
const completion = new Promise((resolve, reject) => {
|
|
22
|
+
child.on("error", reject);
|
|
23
|
+
child.on("close", (status) => {
|
|
24
|
+
if (status !== 0)
|
|
25
|
+
reject(new OutpostError("process", `${command.executable} exited with status ${status}`, { status, stderr }));
|
|
26
|
+
else
|
|
27
|
+
resolve({ status: 0, stdout: "", stderr });
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
const pending = [completion];
|
|
31
|
+
if (streams.input)
|
|
32
|
+
pending.push(pipeline(streams.input, child.stdin, { signal }));
|
|
33
|
+
else
|
|
34
|
+
child.stdin.end();
|
|
35
|
+
if (streams.output)
|
|
36
|
+
pending.push(pipeline(child.stdout, streams.output, { signal }));
|
|
37
|
+
else
|
|
38
|
+
child.stdout.resume();
|
|
39
|
+
try {
|
|
40
|
+
await Promise.all(pending);
|
|
41
|
+
return await completion;
|
|
42
|
+
}
|
|
43
|
+
catch (cause) {
|
|
44
|
+
child.kill("SIGKILL");
|
|
45
|
+
streams.input?.destroy();
|
|
46
|
+
streams.output?.destroy();
|
|
47
|
+
await Promise.allSettled(pending);
|
|
48
|
+
signal.throwIfAborted();
|
|
49
|
+
throw cause;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=binary-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-process.js","sourceRoot":"","sources":["../../src/infrastructure/binary-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { CommandResult } from \"../domain/command.types.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type { BinaryStreams } from \"./binary-process.types.ts\";\nimport { processDefaults } from \"./process.constants.ts\";\nimport type { Executor } from \"./process.types.ts\";\nimport { transfer } from \"./transfer.ts\";\n\nexport function binaryExecutor(streams: BinaryStreams): Executor {\n return (command) =>\n transfer(command, async (signal) => {\n signal.throwIfAborted();\n const child = spawn(command.executable, [...(command.arguments ?? [])], {\n cwd: command.directory,\n env: { ...process.env, ...command.variables },\n windowsHide: true,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n signal,\n killSignal: \"SIGKILL\",\n });\n let stderr = \"\";\n child.stderr.on(\"data\", (data: Buffer) => {\n stderr = (stderr + data.toString(\"utf8\")).slice(\n -processDefaults.retainBytes,\n );\n });\n const completion = new Promise<CommandResult>((resolve, reject) => {\n child.on(\"error\", reject);\n child.on(\"close\", (status) => {\n if (status !== 0)\n reject(\n new OutpostError(\n \"process\",\n `${command.executable} exited with status ${status}`,\n { status, stderr },\n ),\n );\n else resolve({ status: 0, stdout: \"\", stderr });\n });\n });\n const pending: Promise<unknown>[] = [completion];\n if (streams.input)\n pending.push(pipeline(streams.input, child.stdin, { signal }));\n else child.stdin.end();\n if (streams.output)\n pending.push(pipeline(child.stdout, streams.output, { signal }));\n else child.stdout.resume();\n try {\n await Promise.all(pending);\n return await completion;\n } catch (cause) {\n child.kill(\"SIGKILL\");\n streams.input?.destroy();\n streams.output?.destroy();\n await Promise.allSettled(pending);\n signal.throwIfAborted();\n throw cause;\n }\n });\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-process.types.js","sourceRoot":"","sources":["../../src/infrastructure/binary-process.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Readable, Writable } from \"node:stream\";\n\nexport interface BinaryStreams {\n readonly input?: Readable;\n readonly output?: Writable;\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { chmod, copyFile, rm, lstat, mkdir, readdir, readlink, symlink, } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, parse, resolve } from "node:path";
|
|
3
|
+
import { OutpostError } from "../domain/errors.js";
|
|
4
|
+
export async function transferDestination(destination) {
|
|
5
|
+
const absolute = resolve(destination);
|
|
6
|
+
for (let path = absolute; path !== parse(path).root; path = dirname(path)) {
|
|
7
|
+
const info = await lstat(path).catch((cause) => {
|
|
8
|
+
if (cause.code === "ENOENT")
|
|
9
|
+
return undefined;
|
|
10
|
+
throw cause;
|
|
11
|
+
});
|
|
12
|
+
if (info?.isSymbolicLink())
|
|
13
|
+
throw new OutpostError("provider", "Transfer destination traverses a symlink", { destination });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export async function copyTransfer(source, destination, signal) {
|
|
17
|
+
signal.throwIfAborted();
|
|
18
|
+
await transferDestination(destination);
|
|
19
|
+
const info = await lstat(source);
|
|
20
|
+
if (info.isDirectory()) {
|
|
21
|
+
await mkdir(destination, { recursive: true });
|
|
22
|
+
for (const name of await readdir(source))
|
|
23
|
+
await copyTransfer(join(source, name), join(destination, name), signal);
|
|
24
|
+
await chmod(destination, info.mode & 0o777);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
await mkdir(dirname(destination), { recursive: true });
|
|
28
|
+
if (info.isSymbolicLink()) {
|
|
29
|
+
await symlink(await readlink(source), destination);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (!info.isFile())
|
|
33
|
+
throw new OutpostError("provider", "Unsupported transfer file type", {
|
|
34
|
+
source,
|
|
35
|
+
});
|
|
36
|
+
await copyFile(source, destination);
|
|
37
|
+
await chmod(destination, info.mode & 0o777);
|
|
38
|
+
}
|
|
39
|
+
export async function removeTransferDirectory(root) {
|
|
40
|
+
async function writable(path) {
|
|
41
|
+
const info = await lstat(path);
|
|
42
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
43
|
+
return;
|
|
44
|
+
await chmod(path, 0o700);
|
|
45
|
+
for (const name of await readdir(path))
|
|
46
|
+
await writable(join(path, name));
|
|
47
|
+
}
|
|
48
|
+
await writable(root);
|
|
49
|
+
await rm(root, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=transfer-copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfer-copy.js","sourceRoot":"","sources":["../../src/infrastructure/transfer-copy.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n chmod,\n copyFile,\n rm,\n lstat,\n mkdir,\n readdir,\n readlink,\n symlink,\n} from \"node:fs/promises\";\nimport { dirname, join, parse, resolve } from \"node:path\";\nimport { OutpostError } from \"../domain/errors.ts\";\n\nexport async function transferDestination(destination: string): Promise<void> {\n const absolute = resolve(destination);\n for (let path = absolute; path !== parse(path).root; path = dirname(path)) {\n const info = await lstat(path).catch((cause: NodeJS.ErrnoException) => {\n if (cause.code === \"ENOENT\") return undefined;\n throw cause;\n });\n if (info?.isSymbolicLink())\n throw new OutpostError(\n \"provider\",\n \"Transfer destination traverses a symlink\",\n { destination },\n );\n }\n}\n\nexport async function copyTransfer(\n source: string,\n destination: string,\n signal: AbortSignal,\n): Promise<void> {\n signal.throwIfAborted();\n await transferDestination(destination);\n const info = await lstat(source);\n if (info.isDirectory()) {\n await mkdir(destination, { recursive: true });\n for (const name of await readdir(source))\n await copyTransfer(join(source, name), join(destination, name), signal);\n await chmod(destination, info.mode & 0o777);\n return;\n }\n await mkdir(dirname(destination), { recursive: true });\n if (info.isSymbolicLink()) {\n await symlink(await readlink(source), destination);\n return;\n }\n if (!info.isFile())\n throw new OutpostError(\"provider\", \"Unsupported transfer file type\", {\n source,\n });\n await copyFile(source, destination);\n await chmod(destination, info.mode & 0o777);\n}\n\nexport async function removeTransferDirectory(root: string): Promise<void> {\n async function writable(path: string): Promise<void> {\n const info = await lstat(path);\n if (!info.isDirectory() || info.isSymbolicLink()) return;\n await chmod(path, 0o700);\n for (const name of await readdir(path)) await writable(join(path, name));\n }\n await writable(root);\n await rm(root, { recursive: true, force: true });\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Command } from "../domain/command.types.ts";
|
|
2
|
+
import type { ContainerRuntime } from "./container.types.ts";
|
|
3
|
+
export declare function containerArchive(runtime: ContainerRuntime, local: Command, remote: Command, upload: boolean, signal: AbortSignal): Promise<void>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PassThrough } from "node:stream";
|
|
2
|
+
import { binaryExecutor } from "../infrastructure/binary-process.js";
|
|
3
|
+
import { containerCommand } from "./container-command.js";
|
|
4
|
+
export async function containerArchive(runtime, local, remote, upload, signal) {
|
|
5
|
+
const pipe = new PassThrough();
|
|
6
|
+
const stop = new AbortController();
|
|
7
|
+
const combined = AbortSignal.any([signal, stop.signal]);
|
|
8
|
+
const host = binaryExecutor(upload ? { output: pipe } : { input: pipe });
|
|
9
|
+
const guest = containerCommand({
|
|
10
|
+
...runtime,
|
|
11
|
+
executor: binaryExecutor(upload ? { input: pipe } : { output: pipe }),
|
|
12
|
+
});
|
|
13
|
+
const pending = [
|
|
14
|
+
host({ ...local, signal: combined }),
|
|
15
|
+
guest({ ...remote, signal: combined }),
|
|
16
|
+
];
|
|
17
|
+
try {
|
|
18
|
+
await Promise.all(pending);
|
|
19
|
+
}
|
|
20
|
+
catch (cause) {
|
|
21
|
+
stop.abort(cause);
|
|
22
|
+
pipe.destroy();
|
|
23
|
+
await Promise.allSettled(pending);
|
|
24
|
+
throw cause;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=container-archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-archive.js","sourceRoot":"","sources":["../../src/providers/container-archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAyB,EACzB,KAAc,EACd,MAAe,EACf,MAAe,EACf,MAAmB;IAEnB,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,gBAAgB,CAAC;QAC7B,GAAG,OAAO;QACV,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KACtE,CAAC,CAAC;IACH,MAAM,OAAO,GAAG;QACd,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACpC,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;KACvC,CAAC;IACF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClB,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import { PassThrough } from \"node:stream\";\nimport type { Command } from \"../domain/command.types.ts\";\nimport { binaryExecutor } from \"../infrastructure/binary-process.ts\";\nimport { containerCommand } from \"./container-command.ts\";\nimport type { ContainerRuntime } from \"./container.types.ts\";\n\nexport async function containerArchive(\n runtime: ContainerRuntime,\n local: Command,\n remote: Command,\n upload: boolean,\n signal: AbortSignal,\n): Promise<void> {\n const pipe = new PassThrough();\n const stop = new AbortController();\n const combined = AbortSignal.any([signal, stop.signal]);\n const host = binaryExecutor(upload ? { output: pipe } : { input: pipe });\n const guest = containerCommand({\n ...runtime,\n executor: binaryExecutor(upload ? { input: pipe } : { output: pipe }),\n });\n const pending = [\n host({ ...local, signal: combined }),\n guest({ ...remote, signal: combined }),\n ];\n try {\n await Promise.all(pending);\n } catch (cause) {\n stop.abort(cause);\n pipe.destroy();\n await Promise.allSettled(pending);\n throw cause;\n }\n}\n"]}
|
|
@@ -37,9 +37,9 @@ export function containerCommand(runtime) {
|
|
|
37
37
|
executable: engine,
|
|
38
38
|
arguments: [
|
|
39
39
|
...flags,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
...(command.interactive && process.stdin.isTTY
|
|
41
|
+
? []
|
|
42
|
+
: ["setsid", "--wait"]),
|
|
43
43
|
"sh",
|
|
44
44
|
"-c",
|
|
45
45
|
wrapper,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container-command.js","sourceRoot":"","sources":["../../src/providers/container-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,MAAM,UAAU,gBAAgB,CAC9B,OAAyB;IAEzB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,IAAI,QAAQ,EAAE;YACZ,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,6BAA6B,CAAC,CAAC;QACpE,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;QACjC,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,gBAAgB,EAAE,MAAM,CAAC;QACzC,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACnD,SAAS,CACP,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACnC,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,CACrC,EACD,yBAAyB,CAC1B,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CACpC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAClD,iBAAiB,KAAK,EAAE;YACxB,KAAK;SACN,CAAC,CACH,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;aACnC,GAAG,CACF,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CACb,UAAU,GAAG,oBAAoB,KAAK,0BAA0B,KAAK,GAAG,CAC3E;aACA,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,MAAM,KAAK,GAAG;YACZ,MAAM;YACN,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YACzD,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,WAAW;YACX,OAAO,CAAC,SAAS,IAAI,IAAI;YACzB,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC5D,IAAI;SACL,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,OAAO,cAAc,KAAK,CAAC,OAAO,CAAC,eAAe,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,yBAAyB,CAAC;QACzH,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;QACzD,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC;gBACpB,GAAG,UAAU;gBACb,UAAU,EAAE,MAAM;gBAClB,SAAS,EAAE;oBACT,GAAG,KAAK;oBACR,
|
|
1
|
+
{"version":3,"file":"container-command.js","sourceRoot":"","sources":["../../src/providers/container-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { invariant, OutpostError } from \"../domain/errors.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { quote } from \"../infrastructure/process.ts\";\nimport { containerDefaults } from \"./container.constants.ts\";\nimport type { ContainerRuntime } from \"./container.types.ts\";\n\nexport function containerCommand(\n runtime: ContainerRuntime,\n): SandboxLease[\"invoke\"] {\n const { engine, config, executor, root, name, env, call, isClosed } = runtime;\n return async (command) => {\n if (isClosed())\n throw new OutpostError(\"provider\", \"Container sandbox is closed\");\n command.signal?.throwIfAborted();\n const id = randomUUID();\n const pidFile = `/tmp/outpost-${id}.pid`;\n const variables = { ...env, ...command.variables };\n invariant(\n Object.keys(variables).every((key) =>\n /^[A-Za-z_][A-Za-z0-9_]*$/.test(key),\n ),\n \"Invalid environment key\",\n );\n const environment = Object.fromEntries(\n Object.entries(variables).map(([, value], index) => [\n `OUTPOST_VALUE_${index}`,\n value,\n ]),\n );\n const exports = Object.keys(variables)\n .map(\n (key, index) =>\n `export ${key}=\"$OUTPOST_VALUE_${index}\"; unset OUTPOST_VALUE_${index};`,\n )\n .join(\" \");\n const flags = [\n \"exec\",\n command.interactive && process.stdin.isTTY ? \"-it\" : \"-i\",\n ...(command.elevated ? [\"--user\", \"0:0\"] : []),\n \"--workdir\",\n command.directory ?? root,\n ...Object.keys(environment).flatMap((key) => [\"--env\", key]),\n name,\n ];\n const wrapper = `${exports} echo $$ > ${quote(pidFile)}; test ! -f ${quote(pidFile + \".cancel\")} || exit 130; exec \"$@\"`;\n const { directory: _directory, ...invocation } = command;\n let interrupted = false;\n try {\n return await executor({\n ...invocation,\n executable: engine,\n arguments: [\n ...flags,\n ...(command.interactive && process.stdin.isTTY\n ? []\n : [\"setsid\", \"--wait\"]),\n \"sh\",\n \"-c\",\n wrapper,\n \"outpost\",\n command.executable,\n ...(command.arguments ?? []),\n ],\n variables: environment,\n retain:\n command.retain ?? config.retain ?? containerDefaults.retainBytes,\n });\n } catch (cause) {\n interrupted = true;\n try {\n await call([\n \"exec\",\n ...(command.elevated ? [\"--user\", \"0:0\"] : []),\n name,\n \"sh\",\n \"-c\",\n `touch ${quote(pidFile + \".cancel\")}; if [ -f ${quote(pidFile)} ]; then p=$(cat ${quote(pidFile)}); kill -TERM -\"$p\" 2>/dev/null || true; sleep 0.1; kill -KILL -\"$p\" 2>/dev/null || true; fi`,\n ]);\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Command cancellation could not be confirmed\",\n );\n }\n throw cause;\n } finally {\n if (!isClosed() && !interrupted)\n await call([\"exec\", name, \"rm\", \"-f\", pidFile]).catch(() => undefined);\n }\n };\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { SandboxLease } from "../domain/sandbox.types.ts";
|
|
2
|
+
import { containerArchive } from "./container-archive.ts";
|
|
2
3
|
import type { ContainerRuntime } from "./container.types.ts";
|
|
3
|
-
export declare function containerFiles(
|
|
4
|
+
export declare function containerFiles(runtime: ContainerRuntime, archive?: typeof containerArchive): Pick<SandboxLease, "upload" | "download">;
|