@ai-hero/sandcastle 0.0.1
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 +284 -0
- package/dist/AgentProvider.d.ts +8 -0
- package/dist/AgentProvider.d.ts.map +1 -0
- package/dist/AgentProvider.js +60 -0
- package/dist/AgentProvider.js.map +1 -0
- package/dist/Config.d.ts +35 -0
- package/dist/Config.d.ts.map +1 -0
- package/dist/Config.js +56 -0
- package/dist/Config.js.map +1 -0
- package/dist/CopyToSandbox.d.ts +8 -0
- package/dist/CopyToSandbox.d.ts.map +1 -0
- package/dist/CopyToSandbox.js +32 -0
- package/dist/CopyToSandbox.js.map +1 -0
- package/dist/Display.d.ts +52 -0
- package/dist/Display.d.ts.map +1 -0
- package/dist/Display.js +132 -0
- package/dist/Display.js.map +1 -0
- package/dist/DockerLifecycle.d.ts +37 -0
- package/dist/DockerLifecycle.d.ts.map +1 -0
- package/dist/DockerLifecycle.js +109 -0
- package/dist/DockerLifecycle.js.map +1 -0
- package/dist/DockerSandbox.d.ts +6 -0
- package/dist/DockerSandbox.d.ts.map +1 -0
- package/dist/DockerSandbox.js +122 -0
- package/dist/DockerSandbox.js.map +1 -0
- package/dist/EnvResolver.d.ts +11 -0
- package/dist/EnvResolver.d.ts.map +1 -0
- package/dist/EnvResolver.js +43 -0
- package/dist/EnvResolver.js.map +1 -0
- package/dist/ErrorHandler.d.ts +15 -0
- package/dist/ErrorHandler.d.ts.map +1 -0
- package/dist/ErrorHandler.js +58 -0
- package/dist/ErrorHandler.js.map +1 -0
- package/dist/FilesystemSandbox.d.ts +6 -0
- package/dist/FilesystemSandbox.d.ts.map +1 -0
- package/dist/FilesystemSandbox.js +83 -0
- package/dist/FilesystemSandbox.js.map +1 -0
- package/dist/InitService.d.ts +11 -0
- package/dist/InitService.d.ts.map +1 -0
- package/dist/InitService.js +111 -0
- package/dist/InitService.js.map +1 -0
- package/dist/Orchestrator.d.ts +49 -0
- package/dist/Orchestrator.d.ts.map +1 -0
- package/dist/Orchestrator.js +155 -0
- package/dist/Orchestrator.js.map +1 -0
- package/dist/PromptArgumentSubstitution.d.ts +6 -0
- package/dist/PromptArgumentSubstitution.d.ts.map +1 -0
- package/dist/PromptArgumentSubstitution.js +33 -0
- package/dist/PromptArgumentSubstitution.js.map +1 -0
- package/dist/PromptPreprocessor.d.ts +7 -0
- package/dist/PromptPreprocessor.d.ts.map +1 -0
- package/dist/PromptPreprocessor.js +34 -0
- package/dist/PromptPreprocessor.js.map +1 -0
- package/dist/PromptResolver.d.ts +9 -0
- package/dist/PromptResolver.d.ts.map +1 -0
- package/dist/PromptResolver.js +26 -0
- package/dist/PromptResolver.js.map +1 -0
- package/dist/RecoveryMessage.d.ts +15 -0
- package/dist/RecoveryMessage.d.ts.map +1 -0
- package/dist/RecoveryMessage.js +81 -0
- package/dist/RecoveryMessage.js.map +1 -0
- package/dist/Sandbox.d.ts +23 -0
- package/dist/Sandbox.d.ts.map +1 -0
- package/dist/Sandbox.js +5 -0
- package/dist/Sandbox.js.map +1 -0
- package/dist/SandboxFactory.d.ts +56 -0
- package/dist/SandboxFactory.d.ts.map +1 -0
- package/dist/SandboxFactory.js +219 -0
- package/dist/SandboxFactory.js.map +1 -0
- package/dist/SandboxLifecycle.d.ts +32 -0
- package/dist/SandboxLifecycle.d.ts.map +1 -0
- package/dist/SandboxLifecycle.js +152 -0
- package/dist/SandboxLifecycle.js.map +1 -0
- package/dist/SyncService.d.ts +20 -0
- package/dist/SyncService.d.ts.map +1 -0
- package/dist/SyncService.js +504 -0
- package/dist/SyncService.js.map +1 -0
- package/dist/TokenResolver.d.ts +6 -0
- package/dist/TokenResolver.d.ts.map +1 -0
- package/dist/TokenResolver.js +43 -0
- package/dist/TokenResolver.js.map +1 -0
- package/dist/WorktreeManager.d.ts +42 -0
- package/dist/WorktreeManager.d.ts.map +1 -0
- package/dist/WorktreeManager.js +170 -0
- package/dist/WorktreeManager.js.map +1 -0
- package/dist/cli.d.ts +22 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +217 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +95 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -0
- package/dist/run.d.ts +91 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +155 -0
- package/dist/run.js.map +1 -0
- package/dist/templates/blank/main.ts +9 -0
- package/dist/templates/blank/prompt.md +12 -0
- package/dist/templates/blank/template.json +4 -0
- package/dist/templates/parallel-planner/implement-prompt.md +62 -0
- package/dist/templates/parallel-planner/main.ts +200 -0
- package/dist/templates/parallel-planner/merge-prompt.md +22 -0
- package/dist/templates/parallel-planner/plan-prompt.md +33 -0
- package/dist/templates/parallel-planner/template.json +4 -0
- package/dist/templates/sequential-reviewer/implement-prompt.md +62 -0
- package/dist/templates/sequential-reviewer/main.ts +102 -0
- package/dist/templates/sequential-reviewer/review-prompt.md +43 -0
- package/dist/templates/sequential-reviewer/template.json +4 -0
- package/dist/templates/simple-loop/main.ts +37 -0
- package/dist/templates/simple-loop/prompt.md +51 -0
- package/dist/templates/simple-loop/template.json +4 -0
- package/dist/templates.d.ts +2 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +26 -0
- package/dist/templates.js.map +1 -0
- package/dist/terminalCleanup.d.ts +30 -0
- package/dist/terminalCleanup.d.ts.map +1 -0
- package/dist/terminalCleanup.js +37 -0
- package/dist/terminalCleanup.js.map +1 -0
- package/dist/testSandbox.d.ts +8 -0
- package/dist/testSandbox.d.ts.map +1 -0
- package/dist/testSandbox.js +101 -0
- package/dist/testSandbox.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { FileSystem } from "@effect/platform";
|
|
3
|
+
import { WorktreeError } from "./errors.js";
|
|
4
|
+
/** Sanitize an agent name for use in branch names and directory names. */
|
|
5
|
+
export declare const sanitizeAgentName: (name: string) => string;
|
|
6
|
+
/**
|
|
7
|
+
* Generates a temporary branch name.
|
|
8
|
+
* When agentName is provided: `sandcastle/<sanitized-agent>/<YYYYMMDD-HHMMSS>`.
|
|
9
|
+
* Otherwise: `sandcastle/<YYYYMMDD-HHMMSS>`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const generateTempBranchName: (agentName?: string | undefined) => string;
|
|
12
|
+
/** Returns the name of the currently checked-out branch in the given repo directory. */
|
|
13
|
+
export declare const getCurrentBranch: (repoDir: string) => Effect.Effect<string, WorktreeError, never>;
|
|
14
|
+
export interface WorktreeInfo {
|
|
15
|
+
path: string;
|
|
16
|
+
branch: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a git worktree at `.sandcastle/worktrees/<name>/`.
|
|
20
|
+
*
|
|
21
|
+
* - If `branch` is specified, checks out that branch.
|
|
22
|
+
* - If not, creates a temporary `sandcastle/<timestamp>` branch.
|
|
23
|
+
*
|
|
24
|
+
* Fails with a clear error if the branch is already checked out in another worktree.
|
|
25
|
+
*/
|
|
26
|
+
export declare const create: (repoDir: string, opts?: {
|
|
27
|
+
branch?: string | undefined;
|
|
28
|
+
agentName?: string | undefined;
|
|
29
|
+
} | undefined) => Effect.Effect<WorktreeInfo, WorktreeError, FileSystem.FileSystem>;
|
|
30
|
+
/**
|
|
31
|
+
* Removes a worktree and its git metadata.
|
|
32
|
+
*
|
|
33
|
+
* The `worktreePath` must be a path inside `.sandcastle/worktrees/` so that
|
|
34
|
+
* the main repository directory can be derived from it.
|
|
35
|
+
*/
|
|
36
|
+
export declare const remove: (worktreePath: string) => Effect.Effect<void, WorktreeError, never>;
|
|
37
|
+
/**
|
|
38
|
+
* Prunes stale git worktree metadata and removes orphaned directories under
|
|
39
|
+
* `.sandcastle/worktrees/`.
|
|
40
|
+
*/
|
|
41
|
+
export declare const pruneStale: (repoDir: string) => Effect.Effect<void, WorktreeError, FileSystem.FileSystem>;
|
|
42
|
+
//# sourceMappingURL=WorktreeManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeManager.d.ts","sourceRoot":"","sources":["../src/WorktreeManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAW5C,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,0BACiB,CAAC;AAsBhD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,4CAMlC,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,kEAK1B,CAAC;AAEJ,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAsCD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM;;;mFA+Ef,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,MAAM,qEAQlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,gFAsDnB,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { FileSystem } from "@effect/platform";
|
|
3
|
+
import { execFile } from "node:child_process";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { WorktreeError } from "./errors.js";
|
|
6
|
+
/** Format a timestamp as YYYYMMDD-HHMMSS */
|
|
7
|
+
const formatTimestamp = (date) => {
|
|
8
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
9
|
+
return (`${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-` +
|
|
10
|
+
`${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`);
|
|
11
|
+
};
|
|
12
|
+
/** Sanitize an agent name for use in branch names and directory names. */
|
|
13
|
+
export const sanitizeAgentName = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
14
|
+
const execGit = (args, cwd) => Effect.async((resume) => {
|
|
15
|
+
execFile("git", args, { cwd }, (error, stdout, stderr) => {
|
|
16
|
+
if (error) {
|
|
17
|
+
resume(Effect.fail(new WorktreeError({
|
|
18
|
+
message: stderr?.trim() || error.message,
|
|
19
|
+
})));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
resume(Effect.succeed(stdout));
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Generates a temporary branch name.
|
|
28
|
+
* When agentName is provided: `sandcastle/<sanitized-agent>/<YYYYMMDD-HHMMSS>`.
|
|
29
|
+
* Otherwise: `sandcastle/<YYYYMMDD-HHMMSS>`.
|
|
30
|
+
*/
|
|
31
|
+
export const generateTempBranchName = (agentName) => {
|
|
32
|
+
const ts = formatTimestamp(new Date());
|
|
33
|
+
if (agentName) {
|
|
34
|
+
return `sandcastle/${sanitizeAgentName(agentName)}/${ts}`;
|
|
35
|
+
}
|
|
36
|
+
return `sandcastle/${ts}`;
|
|
37
|
+
};
|
|
38
|
+
/** Returns the name of the currently checked-out branch in the given repo directory. */
|
|
39
|
+
export const getCurrentBranch = (repoDir) => execGit(["rev-parse", "--abbrev-ref", "HEAD"], repoDir).pipe(Effect.map((output) => output.trim()));
|
|
40
|
+
/** Parses `git worktree list --porcelain` output into structured entries. */
|
|
41
|
+
const listWorktrees = (repoDir) => execGit(["worktree", "list", "--porcelain"], repoDir).pipe(Effect.map((output) => {
|
|
42
|
+
const entries = [];
|
|
43
|
+
let currentPath = null;
|
|
44
|
+
let currentBranch = null;
|
|
45
|
+
for (const line of output.split("\n")) {
|
|
46
|
+
if (line.startsWith("worktree ")) {
|
|
47
|
+
if (currentPath !== null) {
|
|
48
|
+
entries.push({ path: currentPath, branch: currentBranch });
|
|
49
|
+
}
|
|
50
|
+
currentPath = line.slice("worktree ".length).trim();
|
|
51
|
+
currentBranch = null;
|
|
52
|
+
}
|
|
53
|
+
else if (line.startsWith("branch ")) {
|
|
54
|
+
// "branch refs/heads/my-branch" -> "my-branch"
|
|
55
|
+
currentBranch = line.slice("branch refs/heads/".length).trim();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (currentPath !== null) {
|
|
59
|
+
entries.push({ path: currentPath, branch: currentBranch });
|
|
60
|
+
}
|
|
61
|
+
return entries;
|
|
62
|
+
}));
|
|
63
|
+
/**
|
|
64
|
+
* Creates a git worktree at `.sandcastle/worktrees/<name>/`.
|
|
65
|
+
*
|
|
66
|
+
* - If `branch` is specified, checks out that branch.
|
|
67
|
+
* - If not, creates a temporary `sandcastle/<timestamp>` branch.
|
|
68
|
+
*
|
|
69
|
+
* Fails with a clear error if the branch is already checked out in another worktree.
|
|
70
|
+
*/
|
|
71
|
+
export const create = (repoDir, opts) => Effect.gen(function* () {
|
|
72
|
+
const fs = yield* FileSystem.FileSystem;
|
|
73
|
+
const worktreesDir = join(repoDir, ".sandcastle", "worktrees");
|
|
74
|
+
yield* fs
|
|
75
|
+
.makeDirectory(worktreesDir, { recursive: true })
|
|
76
|
+
.pipe(Effect.mapError((e) => new WorktreeError({ message: e.message })));
|
|
77
|
+
let branch;
|
|
78
|
+
let worktreeName;
|
|
79
|
+
if (opts?.branch) {
|
|
80
|
+
branch = opts.branch;
|
|
81
|
+
worktreeName = branch.replace(/\//g, "-");
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const timestamp = formatTimestamp(new Date());
|
|
85
|
+
if (opts?.agentName) {
|
|
86
|
+
const sanitized = sanitizeAgentName(opts.agentName);
|
|
87
|
+
branch = `sandcastle/${sanitized}/${timestamp}`;
|
|
88
|
+
worktreeName = `sandcastle-${sanitized}-${timestamp}`;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
branch = `sandcastle/${timestamp}`;
|
|
92
|
+
worktreeName = `sandcastle-${timestamp}`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const worktreePath = join(worktreesDir, worktreeName);
|
|
96
|
+
if (opts?.branch) {
|
|
97
|
+
// Proactively detect collision before git produces a confusing error
|
|
98
|
+
const existing = yield* listWorktrees(repoDir);
|
|
99
|
+
const collision = existing.find((wt) => wt.branch === branch);
|
|
100
|
+
if (collision) {
|
|
101
|
+
yield* Effect.fail(new WorktreeError({
|
|
102
|
+
message: `Branch '${branch}' is already checked out in worktree at '${collision.path}'. ` +
|
|
103
|
+
`Use a different branch name, or wait for the other run to finish.`,
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
yield* execGit(["worktree", "add", worktreePath, branch], repoDir).pipe(Effect.catchAll((e) => {
|
|
107
|
+
if (e.message.includes("invalid reference")) {
|
|
108
|
+
return execGit(["worktree", "add", "-b", branch, worktreePath, "HEAD"], repoDir);
|
|
109
|
+
}
|
|
110
|
+
return Effect.fail(e);
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
yield* execGit(["worktree", "add", "-b", branch, worktreePath, "HEAD"], repoDir).pipe(Effect.catchAll((e) => {
|
|
115
|
+
if (e.message.includes("already checked out") ||
|
|
116
|
+
e.message.includes("already exists")) {
|
|
117
|
+
return Effect.fail(new WorktreeError({
|
|
118
|
+
message: `Branch '${branch}' is already checked out in another worktree. ` +
|
|
119
|
+
`Use a different branch name, or wait for the other run to finish.`,
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
return Effect.fail(e);
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
return { path: worktreePath, branch };
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* Removes a worktree and its git metadata.
|
|
129
|
+
*
|
|
130
|
+
* The `worktreePath` must be a path inside `.sandcastle/worktrees/` so that
|
|
131
|
+
* the main repository directory can be derived from it.
|
|
132
|
+
*/
|
|
133
|
+
export const remove = (worktreePath) => {
|
|
134
|
+
// Derive the main repo dir: worktreePath = <repoDir>/.sandcastle/worktrees/<name>
|
|
135
|
+
const repoDir = join(worktreePath, "..", "..", "..");
|
|
136
|
+
return execGit(["worktree", "remove", "--force", worktreePath], repoDir).pipe(Effect.asVoid);
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Prunes stale git worktree metadata and removes orphaned directories under
|
|
140
|
+
* `.sandcastle/worktrees/`.
|
|
141
|
+
*/
|
|
142
|
+
export const pruneStale = (repoDir) => Effect.gen(function* () {
|
|
143
|
+
const fs = yield* FileSystem.FileSystem;
|
|
144
|
+
// Let git clean up metadata for worktrees whose directories are gone
|
|
145
|
+
yield* execGit(["worktree", "prune"], repoDir);
|
|
146
|
+
const worktreesDir = join(repoDir, ".sandcastle", "worktrees");
|
|
147
|
+
// Read directory entries — return null if directory doesn't exist
|
|
148
|
+
const entries = yield* fs.readDirectory(worktreesDir).pipe(Effect.map((es) => es), Effect.catchSome((e) => e._tag === "SystemError" && e.reason === "NotFound"
|
|
149
|
+
? Option.some(Effect.succeed(null))
|
|
150
|
+
: Option.none()), Effect.mapError((e) => new WorktreeError({ message: e.message })));
|
|
151
|
+
if (entries === null)
|
|
152
|
+
return;
|
|
153
|
+
// Get the list of active worktree paths from git
|
|
154
|
+
const worktreeList = yield* execGit(["worktree", "list", "--porcelain"], repoDir);
|
|
155
|
+
const activeWorktreePaths = new Set(worktreeList
|
|
156
|
+
.split("\n")
|
|
157
|
+
.filter((line) => line.startsWith("worktree "))
|
|
158
|
+
.map((line) => line.slice("worktree ".length).trim()));
|
|
159
|
+
// Remove any directory under .sandcastle/worktrees/ that is not an active worktree
|
|
160
|
+
for (const entry of entries) {
|
|
161
|
+
const entryPath = join(worktreesDir, entry);
|
|
162
|
+
const isDir = yield* fs.stat(entryPath).pipe(Effect.map((s) => s.type === "Directory"), Effect.catchAll(() => Effect.succeed(false)));
|
|
163
|
+
if (isDir && !activeWorktreePaths.has(entryPath)) {
|
|
164
|
+
yield* fs.remove(entryPath, { recursive: true, force: true }).pipe(Effect.mapError((e) => new WorktreeError({
|
|
165
|
+
message: `Failed to remove ${entryPath}: ${e.message}`,
|
|
166
|
+
})));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=WorktreeManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeManager.js","sourceRoot":"","sources":["../src/WorktreeManager.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Command } from "@effect/cli";
|
|
2
|
+
import { FileSystem } from "@effect/platform";
|
|
3
|
+
import { Effect } from "effect";
|
|
4
|
+
import { Display } from "./Display.js";
|
|
5
|
+
export declare const sandcastle: Command.Command<"sandcastle", Display | FileSystem.FileSystem, import("./errors.js").SandboxError, {
|
|
6
|
+
readonly subcommand: import("effect/Option").Option<{
|
|
7
|
+
readonly imageName: import("effect/Option").Option<string>;
|
|
8
|
+
readonly agent: import("effect/Option").Option<string>;
|
|
9
|
+
readonly template: import("effect/Option").Option<string>;
|
|
10
|
+
} | {
|
|
11
|
+
readonly imageName: import("effect/Option").Option<string>;
|
|
12
|
+
readonly dockerfile: import("effect/Option").Option<string>;
|
|
13
|
+
} | {
|
|
14
|
+
readonly imageName: import("effect/Option").Option<string>;
|
|
15
|
+
} | {
|
|
16
|
+
readonly imageName: import("effect/Option").Option<string>;
|
|
17
|
+
readonly model: import("effect/Option").Option<string>;
|
|
18
|
+
readonly agent: import("effect/Option").Option<string>;
|
|
19
|
+
}>;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const cli: (args: readonly string[]) => Effect.Effect<void, import("./errors.js").SandboxError | import("@effect/cli/ValidationError").ValidationError, Display | import("@effect/cli/CliApp").CliApp.Environment>;
|
|
22
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAW,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAS,MAAM,QAAQ,CAAC;AAKvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAyWvC,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;EAOtB,CAAC;AAEF,eAAO,MAAM,GAAG,yMAGd,CAAC"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { Command, Options } from "@effect/cli";
|
|
2
|
+
import { FileSystem } from "@effect/platform";
|
|
3
|
+
import { NodeFileSystem } from "@effect/platform-node";
|
|
4
|
+
import { Effect, Layer } from "effect";
|
|
5
|
+
import * as clack from "@clack/prompts";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { styleText } from "node:util";
|
|
9
|
+
import { Display } from "./Display.js";
|
|
10
|
+
import { DEFAULT_MODEL } from "./Orchestrator.js";
|
|
11
|
+
import { buildImage, removeImage } from "./DockerLifecycle.js";
|
|
12
|
+
import { scaffold, listTemplates, getNextStepsLines } from "./InitService.js";
|
|
13
|
+
import { defaultImageName } from "./run.js";
|
|
14
|
+
import { getAgentProvider } from "./AgentProvider.js";
|
|
15
|
+
import { AgentError, ConfigDirError, InitError } from "./errors.js";
|
|
16
|
+
import { SandboxFactory, WorktreeDockerSandboxFactory, WorktreeSandboxConfig, SANDBOX_WORKSPACE_DIR, } from "./SandboxFactory.js";
|
|
17
|
+
import { withSandboxLifecycle } from "./SandboxLifecycle.js";
|
|
18
|
+
import { resolveEnv } from "./EnvResolver.js";
|
|
19
|
+
// --- Shared options ---
|
|
20
|
+
const imageNameOption = Options.text("image-name").pipe(Options.withDescription("Docker image name"), Options.optional);
|
|
21
|
+
const resolveImageName = (cliFlag, cwd) => (cliFlag._tag === "Some" ? cliFlag.value : defaultImageName(cwd));
|
|
22
|
+
const agentOption = Options.text("agent").pipe(Options.withDescription("Agent provider to use (e.g. claude-code)"), Options.optional);
|
|
23
|
+
// --- Config directory check ---
|
|
24
|
+
const CONFIG_DIR = ".sandcastle";
|
|
25
|
+
const requireConfigDir = (cwd) => Effect.gen(function* () {
|
|
26
|
+
const fs = yield* FileSystem.FileSystem;
|
|
27
|
+
const exists = yield* fs
|
|
28
|
+
.exists(join(cwd, CONFIG_DIR))
|
|
29
|
+
.pipe(Effect.catchAll(() => Effect.succeed(false)));
|
|
30
|
+
if (!exists) {
|
|
31
|
+
yield* Effect.fail(new ConfigDirError({
|
|
32
|
+
message: "No .sandcastle/ found. Run `sandcastle init` first.",
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
// --- Init command ---
|
|
37
|
+
const templateOption = Options.text("template").pipe(Options.withDescription("Template to scaffold (e.g. blank, simple-loop, parallel-planner)"), Options.optional);
|
|
38
|
+
const initCommand = Command.make("init", {
|
|
39
|
+
imageName: imageNameOption,
|
|
40
|
+
agent: agentOption,
|
|
41
|
+
template: templateOption,
|
|
42
|
+
}, ({ imageName: imageNameFlag, agent, template }) => Effect.gen(function* () {
|
|
43
|
+
const d = yield* Display;
|
|
44
|
+
const cwd = process.cwd();
|
|
45
|
+
const imageName = resolveImageName(imageNameFlag, cwd);
|
|
46
|
+
// Resolve agent provider: CLI flag > default
|
|
47
|
+
const agentName = agent._tag === "Some" ? agent.value : "claude-code";
|
|
48
|
+
const provider = yield* Effect.try({
|
|
49
|
+
try: () => getAgentProvider(agentName),
|
|
50
|
+
catch: (e) => new InitError({
|
|
51
|
+
message: `${e instanceof Error ? e.message : e}`,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
// Resolve template: CLI flag > interactive select
|
|
55
|
+
const templates = listTemplates();
|
|
56
|
+
let selectedTemplate;
|
|
57
|
+
if (template._tag === "Some") {
|
|
58
|
+
const t = template.value;
|
|
59
|
+
const valid = templates.find((tmpl) => tmpl.name === t);
|
|
60
|
+
if (!valid) {
|
|
61
|
+
const names = templates.map((tmpl) => tmpl.name).join(", ");
|
|
62
|
+
yield* Effect.fail(new InitError({
|
|
63
|
+
message: `Unknown template "${t}". Available: ${names}`,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
selectedTemplate = t;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const selected = yield* Effect.promise(() => clack.select({
|
|
70
|
+
message: "Select a template:",
|
|
71
|
+
initialValue: "blank",
|
|
72
|
+
options: templates.map((tmpl) => ({
|
|
73
|
+
value: tmpl.name,
|
|
74
|
+
label: tmpl.name,
|
|
75
|
+
hint: tmpl.description,
|
|
76
|
+
})),
|
|
77
|
+
}));
|
|
78
|
+
if (clack.isCancel(selected)) {
|
|
79
|
+
yield* Effect.fail(new InitError({ message: "Template selection cancelled." }));
|
|
80
|
+
}
|
|
81
|
+
selectedTemplate = selected;
|
|
82
|
+
}
|
|
83
|
+
yield* d.spinner("Scaffolding .sandcastle/ config directory...", scaffold(cwd, provider, selectedTemplate).pipe(Effect.mapError((e) => new InitError({
|
|
84
|
+
message: `${e instanceof Error ? e.message : e}`,
|
|
85
|
+
}))));
|
|
86
|
+
// Prompt user before building image
|
|
87
|
+
const shouldBuild = yield* Effect.promise(() => clack.confirm({
|
|
88
|
+
message: "Build the default Docker image now?",
|
|
89
|
+
initialValue: true,
|
|
90
|
+
}));
|
|
91
|
+
if (shouldBuild === true) {
|
|
92
|
+
const dockerfileDir = join(cwd, CONFIG_DIR);
|
|
93
|
+
yield* d.spinner(`Building Docker image '${imageName}'...`, buildImage(imageName, dockerfileDir));
|
|
94
|
+
yield* d.status("Init complete! Image built successfully.", "success");
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
yield* d.status("Init complete! Run `sandcastle build-image` to build the Docker image later.", "success");
|
|
98
|
+
}
|
|
99
|
+
// Show template-specific next steps
|
|
100
|
+
const nextSteps = getNextStepsLines(selectedTemplate, provider);
|
|
101
|
+
for (const [i, line] of nextSteps.entries()) {
|
|
102
|
+
yield* d.text(i === 0 ? line : styleText("dim", line));
|
|
103
|
+
}
|
|
104
|
+
}));
|
|
105
|
+
// --- Build-image command ---
|
|
106
|
+
const dockerfileOption = Options.file("dockerfile").pipe(Options.withDescription("Path to a custom Dockerfile (build context will be the current working directory)"), Options.optional);
|
|
107
|
+
const buildImageCommand = Command.make("build-image", {
|
|
108
|
+
imageName: imageNameOption,
|
|
109
|
+
dockerfile: dockerfileOption,
|
|
110
|
+
}, ({ imageName: imageNameFlag, dockerfile }) => Effect.gen(function* () {
|
|
111
|
+
const d = yield* Display;
|
|
112
|
+
const cwd = process.cwd();
|
|
113
|
+
yield* requireConfigDir(cwd);
|
|
114
|
+
const imageName = resolveImageName(imageNameFlag, cwd);
|
|
115
|
+
const dockerfileDir = join(cwd, CONFIG_DIR);
|
|
116
|
+
const dockerfilePath = dockerfile._tag === "Some" ? dockerfile.value : undefined;
|
|
117
|
+
yield* d.spinner(`Building Docker image '${imageName}'...`, buildImage(imageName, dockerfileDir, {
|
|
118
|
+
dockerfile: dockerfilePath,
|
|
119
|
+
}));
|
|
120
|
+
yield* d.status("Build complete!", "success");
|
|
121
|
+
}));
|
|
122
|
+
// --- Remove-image command ---
|
|
123
|
+
const removeImageCommand = Command.make("remove-image", {
|
|
124
|
+
imageName: imageNameOption,
|
|
125
|
+
}, ({ imageName: imageNameFlag }) => Effect.gen(function* () {
|
|
126
|
+
const d = yield* Display;
|
|
127
|
+
const cwd = process.cwd();
|
|
128
|
+
const imageName = resolveImageName(imageNameFlag, cwd);
|
|
129
|
+
yield* d.spinner(`Removing Docker image '${imageName}'...`, removeImage(imageName));
|
|
130
|
+
yield* d.status("Image removed.", "success");
|
|
131
|
+
}));
|
|
132
|
+
// --- Interactive command ---
|
|
133
|
+
const modelOption = Options.text("model").pipe(Options.withDescription("Model to use for the agent (e.g. claude-sonnet-4-6)"), Options.optional);
|
|
134
|
+
const interactiveSession = (options) => Effect.gen(function* () {
|
|
135
|
+
const { hostRepoDir } = options;
|
|
136
|
+
const sandboxRepoDir = SANDBOX_WORKSPACE_DIR;
|
|
137
|
+
const resolvedModel = options.model ?? DEFAULT_MODEL;
|
|
138
|
+
const factory = yield* SandboxFactory;
|
|
139
|
+
const d = yield* Display;
|
|
140
|
+
yield* factory.withSandbox(({ hostWorktreePath }) => withSandboxLifecycle({ hostRepoDir, sandboxRepoDir, hostWorktreePath }, (ctx) => Effect.gen(function* () {
|
|
141
|
+
// Get container ID for docker exec -it
|
|
142
|
+
const hostnameResult = yield* ctx.sandbox.exec("hostname");
|
|
143
|
+
const containerId = hostnameResult.stdout.trim();
|
|
144
|
+
// Launch interactive Claude session with TTY passthrough
|
|
145
|
+
yield* d.status("Launching interactive Claude session...", "info");
|
|
146
|
+
const exitCode = yield* Effect.async((resume) => {
|
|
147
|
+
const proc = spawn("docker", [
|
|
148
|
+
"exec",
|
|
149
|
+
"-it",
|
|
150
|
+
"-w",
|
|
151
|
+
ctx.sandboxRepoDir,
|
|
152
|
+
containerId,
|
|
153
|
+
"claude",
|
|
154
|
+
"--dangerously-skip-permissions",
|
|
155
|
+
"--model",
|
|
156
|
+
resolvedModel,
|
|
157
|
+
], { stdio: "inherit" });
|
|
158
|
+
proc.on("error", (error) => {
|
|
159
|
+
resume(Effect.fail(new AgentError({
|
|
160
|
+
message: `Failed to launch Claude: ${error.message}`,
|
|
161
|
+
})));
|
|
162
|
+
});
|
|
163
|
+
proc.on("close", (code) => {
|
|
164
|
+
resume(Effect.succeed(code ?? 0));
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
yield* d.status(`Session ended (exit code ${exitCode}). Syncing changes back...`, "info");
|
|
168
|
+
})));
|
|
169
|
+
});
|
|
170
|
+
const interactiveCommand = Command.make("interactive", {
|
|
171
|
+
imageName: imageNameOption,
|
|
172
|
+
model: modelOption,
|
|
173
|
+
agent: agentOption,
|
|
174
|
+
}, ({ imageName: imageNameFlag, model, agent }) => Effect.gen(function* () {
|
|
175
|
+
const hostRepoDir = process.cwd();
|
|
176
|
+
yield* requireConfigDir(hostRepoDir);
|
|
177
|
+
// Resolve agent provider: CLI flag > default
|
|
178
|
+
const imageName = resolveImageName(imageNameFlag, hostRepoDir);
|
|
179
|
+
const agentName = agent._tag === "Some" ? agent.value : "claude-code";
|
|
180
|
+
const provider = yield* Effect.try({
|
|
181
|
+
try: () => getAgentProvider(agentName),
|
|
182
|
+
catch: (e) => new InitError({
|
|
183
|
+
message: `${e instanceof Error ? e.message : e}`,
|
|
184
|
+
}),
|
|
185
|
+
});
|
|
186
|
+
// Resolve env vars
|
|
187
|
+
const env = yield* resolveEnv(hostRepoDir);
|
|
188
|
+
const resolvedModel = model._tag === "Some" ? model.value : undefined;
|
|
189
|
+
const d = yield* Display;
|
|
190
|
+
yield* d.summary("Sandcastle Interactive", { Image: imageName });
|
|
191
|
+
const factoryLayer = Layer.provide(WorktreeDockerSandboxFactory.layer, Layer.merge(Layer.succeed(WorktreeSandboxConfig, {
|
|
192
|
+
imageName,
|
|
193
|
+
env,
|
|
194
|
+
hostRepoDir,
|
|
195
|
+
}), NodeFileSystem.layer));
|
|
196
|
+
yield* interactiveSession({
|
|
197
|
+
hostRepoDir,
|
|
198
|
+
model: resolvedModel,
|
|
199
|
+
}).pipe(Effect.provide(factoryLayer));
|
|
200
|
+
}));
|
|
201
|
+
// --- Root command ---
|
|
202
|
+
const rootCommand = Command.make("sandcastle", {}, () => Effect.gen(function* () {
|
|
203
|
+
const d = yield* Display;
|
|
204
|
+
yield* d.status("Sandcastle v0.0.1", "info");
|
|
205
|
+
yield* d.status("Use --help to see available commands.", "info");
|
|
206
|
+
}));
|
|
207
|
+
export const sandcastle = rootCommand.pipe(Command.withSubcommands([
|
|
208
|
+
initCommand,
|
|
209
|
+
buildImageCommand,
|
|
210
|
+
removeImageCommand,
|
|
211
|
+
interactiveCommand,
|
|
212
|
+
]));
|
|
213
|
+
export const cli = Command.run(sandcastle, {
|
|
214
|
+
name: "sandcastle",
|
|
215
|
+
version: "0.0.1",
|
|
216
|
+
});
|
|
217
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
declare const ExecError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
2
|
+
readonly _tag: "ExecError";
|
|
3
|
+
} & Readonly<A>;
|
|
4
|
+
/** Command execution failed in the sandbox */
|
|
5
|
+
export declare class ExecError extends ExecError_base<{
|
|
6
|
+
readonly message: string;
|
|
7
|
+
readonly command: string;
|
|
8
|
+
}> {
|
|
9
|
+
}
|
|
10
|
+
declare const ExecHostError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
11
|
+
readonly _tag: "ExecHostError";
|
|
12
|
+
} & Readonly<A>;
|
|
13
|
+
/** Command execution failed on the host */
|
|
14
|
+
export declare class ExecHostError extends ExecHostError_base<{
|
|
15
|
+
readonly message: string;
|
|
16
|
+
readonly command: string;
|
|
17
|
+
}> {
|
|
18
|
+
}
|
|
19
|
+
declare const CopyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
20
|
+
readonly _tag: "CopyError";
|
|
21
|
+
} & Readonly<A>;
|
|
22
|
+
/** File copy between host and sandbox failed */
|
|
23
|
+
export declare class CopyError extends CopyError_base<{
|
|
24
|
+
readonly message: string;
|
|
25
|
+
}> {
|
|
26
|
+
}
|
|
27
|
+
declare const DockerError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
28
|
+
readonly _tag: "DockerError";
|
|
29
|
+
} & Readonly<A>;
|
|
30
|
+
/** Docker infrastructure operation failed */
|
|
31
|
+
export declare class DockerError extends DockerError_base<{
|
|
32
|
+
readonly message: string;
|
|
33
|
+
}> {
|
|
34
|
+
}
|
|
35
|
+
declare const SyncError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
36
|
+
readonly _tag: "SyncError";
|
|
37
|
+
} & Readonly<A>;
|
|
38
|
+
/** Git sync-in or sync-out operation failed */
|
|
39
|
+
export declare class SyncError extends SyncError_base<{
|
|
40
|
+
readonly message: string;
|
|
41
|
+
}> {
|
|
42
|
+
}
|
|
43
|
+
declare const WorktreeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
44
|
+
readonly _tag: "WorktreeError";
|
|
45
|
+
} & Readonly<A>;
|
|
46
|
+
/** Git worktree operation failed */
|
|
47
|
+
export declare class WorktreeError extends WorktreeError_base<{
|
|
48
|
+
readonly message: string;
|
|
49
|
+
}> {
|
|
50
|
+
}
|
|
51
|
+
declare const PromptError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
52
|
+
readonly _tag: "PromptError";
|
|
53
|
+
} & Readonly<A>;
|
|
54
|
+
/** Prompt resolution or preprocessing failed */
|
|
55
|
+
export declare class PromptError extends PromptError_base<{
|
|
56
|
+
readonly message: string;
|
|
57
|
+
}> {
|
|
58
|
+
}
|
|
59
|
+
declare const AgentError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
60
|
+
readonly _tag: "AgentError";
|
|
61
|
+
} & Readonly<A>;
|
|
62
|
+
/** Agent invocation failed */
|
|
63
|
+
export declare class AgentError extends AgentError_base<{
|
|
64
|
+
readonly message: string;
|
|
65
|
+
}> {
|
|
66
|
+
}
|
|
67
|
+
declare const ConfigDirError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
68
|
+
readonly _tag: "ConfigDirError";
|
|
69
|
+
} & Readonly<A>;
|
|
70
|
+
/** .sandcastle/ config directory missing */
|
|
71
|
+
export declare class ConfigDirError extends ConfigDirError_base<{
|
|
72
|
+
readonly message: string;
|
|
73
|
+
}> {
|
|
74
|
+
}
|
|
75
|
+
declare const InitError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
76
|
+
readonly _tag: "InitError";
|
|
77
|
+
} & Readonly<A>;
|
|
78
|
+
/** Initialization or setup operation failed */
|
|
79
|
+
export declare class InitError extends InitError_base<{
|
|
80
|
+
readonly message: string;
|
|
81
|
+
}> {
|
|
82
|
+
}
|
|
83
|
+
declare const TimeoutError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
84
|
+
readonly _tag: "TimeoutError";
|
|
85
|
+
} & Readonly<A>;
|
|
86
|
+
/** Run exceeded the configured timeout */
|
|
87
|
+
export declare class TimeoutError extends TimeoutError_base<{
|
|
88
|
+
readonly message: string;
|
|
89
|
+
readonly timeoutSeconds: number;
|
|
90
|
+
}> {
|
|
91
|
+
}
|
|
92
|
+
/** Union of all sandbox-related errors */
|
|
93
|
+
export type SandboxError = ExecError | ExecHostError | CopyError | DockerError | SyncError | WorktreeError | PromptError | AgentError | ConfigDirError | InitError | TimeoutError;
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAEA,8CAA8C;AAC9C,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,2CAA2C;AAC3C,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,gDAAgD;AAChD,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,6CAA6C;AAC7C,qBAAa,WAAY,SAAQ,iBAAgC;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,+CAA+C;AAC/C,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,oCAAoC;AACpC,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,gDAAgD;AAChD,qBAAa,WAAY,SAAQ,iBAAgC;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,8BAA8B;AAC9B,qBAAa,UAAW,SAAQ,gBAA+B;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,4CAA4C;AAC5C,qBAAa,cAAe,SAAQ,oBAAmC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,+CAA+C;AAC/C,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,0CAA0C;AAC1C,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,CAAC;CAAG;AAEL,0CAA0C;AAC1C,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,aAAa,GACb,SAAS,GACT,WAAW,GACX,SAAS,GACT,aAAa,GACb,WAAW,GACX,UAAU,GACV,cAAc,GACd,SAAS,GACT,YAAY,CAAC"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Data } from "effect";
|
|
2
|
+
/** Command execution failed in the sandbox */
|
|
3
|
+
export class ExecError extends Data.TaggedError("ExecError") {
|
|
4
|
+
}
|
|
5
|
+
/** Command execution failed on the host */
|
|
6
|
+
export class ExecHostError extends Data.TaggedError("ExecHostError") {
|
|
7
|
+
}
|
|
8
|
+
/** File copy between host and sandbox failed */
|
|
9
|
+
export class CopyError extends Data.TaggedError("CopyError") {
|
|
10
|
+
}
|
|
11
|
+
/** Docker infrastructure operation failed */
|
|
12
|
+
export class DockerError extends Data.TaggedError("DockerError") {
|
|
13
|
+
}
|
|
14
|
+
/** Git sync-in or sync-out operation failed */
|
|
15
|
+
export class SyncError extends Data.TaggedError("SyncError") {
|
|
16
|
+
}
|
|
17
|
+
/** Git worktree operation failed */
|
|
18
|
+
export class WorktreeError extends Data.TaggedError("WorktreeError") {
|
|
19
|
+
}
|
|
20
|
+
/** Prompt resolution or preprocessing failed */
|
|
21
|
+
export class PromptError extends Data.TaggedError("PromptError") {
|
|
22
|
+
}
|
|
23
|
+
/** Agent invocation failed */
|
|
24
|
+
export class AgentError extends Data.TaggedError("AgentError") {
|
|
25
|
+
}
|
|
26
|
+
/** .sandcastle/ config directory missing */
|
|
27
|
+
export class ConfigDirError extends Data.TaggedError("ConfigDirError") {
|
|
28
|
+
}
|
|
29
|
+
/** Initialization or setup operation failed */
|
|
30
|
+
export class InitError extends Data.TaggedError("InitError") {
|
|
31
|
+
}
|
|
32
|
+
/** Run exceeded the configured timeout */
|
|
33
|
+
export class TimeoutError extends Data.TaggedError("TimeoutError") {
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,8CAA8C;AAC9C,MAAM,OAAO,SAAU,SAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,CAGzD;CAAG;AAEL,2CAA2C;AAC3C,MAAM,OAAO,aAAc,SAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAGjE;CAAG;AAEL,gDAAgD;AAChD,MAAM,OAAO,SAAU,SAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,CAEzD;CAAG;AAEL,6CAA6C;AAC7C,MAAM,OAAO,WAAY,SAAQ,IAAI,CAAC,WAAW,CAAC,aAAa,CAE7D;CAAG;AAEL,+CAA+C;AAC/C,MAAM,OAAO,SAAU,SAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,CAEzD;CAAG;AAEL,oCAAoC;AACpC,MAAM,OAAO,aAAc,SAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAEjE;CAAG;AAEL,gDAAgD;AAChD,MAAM,OAAO,WAAY,SAAQ,IAAI,CAAC,WAAW,CAAC,aAAa,CAE7D;CAAG;AAEL,8BAA8B;AAC9B,MAAM,OAAO,UAAW,SAAQ,IAAI,CAAC,WAAW,CAAC,YAAY,CAE3D;CAAG;AAEL,4CAA4C;AAC5C,MAAM,OAAO,cAAe,SAAQ,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAEnE;CAAG;AAEL,+CAA+C;AAC/C,MAAM,OAAO,SAAU,SAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,CAEzD;CAAG;AAEL,0CAA0C;AAC1C,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAG/D;CAAG"}
|
package/dist/index.d.ts
ADDED