@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,62 @@
|
|
|
1
|
+
# TASK
|
|
2
|
+
|
|
3
|
+
Fix issue #{{ISSUE_NUMBER}}: {{ISSUE_TITLE}}
|
|
4
|
+
|
|
5
|
+
Pull in the issue using `gh issue view`. If it has a parent PRD, pull that in too.
|
|
6
|
+
|
|
7
|
+
Only work on the issue specified.
|
|
8
|
+
|
|
9
|
+
Work on branch {{BRANCH}}. Make commits, run tests, and close the issue when done.
|
|
10
|
+
|
|
11
|
+
# CONTEXT
|
|
12
|
+
|
|
13
|
+
Here are the last 10 commits:
|
|
14
|
+
|
|
15
|
+
<recent-commits>
|
|
16
|
+
|
|
17
|
+
!`git log -n 10 --format="%H%n%ad%n%B---" --date=short`
|
|
18
|
+
|
|
19
|
+
</recent-commits>
|
|
20
|
+
|
|
21
|
+
# EXPLORATION
|
|
22
|
+
|
|
23
|
+
Explore the repo and fill your context window with relevant information that will allow you to complete the task.
|
|
24
|
+
|
|
25
|
+
Pay extra attention to test files that touch the relevant parts of the code.
|
|
26
|
+
|
|
27
|
+
# EXECUTION
|
|
28
|
+
|
|
29
|
+
If applicable, use RGR to complete the task.
|
|
30
|
+
|
|
31
|
+
1. RED: write one test
|
|
32
|
+
2. GREEN: write the implementation to pass that test
|
|
33
|
+
3. REPEAT until done
|
|
34
|
+
4. REFACTOR the code
|
|
35
|
+
|
|
36
|
+
# FEEDBACK LOOPS
|
|
37
|
+
|
|
38
|
+
Before committing, run `npm run typecheck` and `npm run test` to ensure the tests pass.
|
|
39
|
+
|
|
40
|
+
# COMMIT
|
|
41
|
+
|
|
42
|
+
Make a git commit. The commit message must:
|
|
43
|
+
|
|
44
|
+
1. Start with `RALPH:` prefix
|
|
45
|
+
2. Include task completed + PRD reference
|
|
46
|
+
3. Key decisions made
|
|
47
|
+
4. Files changed
|
|
48
|
+
5. Blockers or notes for next iteration
|
|
49
|
+
|
|
50
|
+
Keep it concise.
|
|
51
|
+
|
|
52
|
+
# THE ISSUE
|
|
53
|
+
|
|
54
|
+
If the task is not complete, leave a comment on the GitHub issue with what was done.
|
|
55
|
+
|
|
56
|
+
Do not close the issue - this will be done later.
|
|
57
|
+
|
|
58
|
+
Once complete, output <promise>COMPLETE</promise>.
|
|
59
|
+
|
|
60
|
+
# FINAL RULES
|
|
61
|
+
|
|
62
|
+
ONLY WORK ON A SINGLE TASK.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Sequential Reviewer — implement-then-review loop
|
|
2
|
+
//
|
|
3
|
+
// This template drives a two-phase workflow per issue:
|
|
4
|
+
// Phase 1 (Implement): A sonnet agent picks an open GitHub issue, works on it
|
|
5
|
+
// on a dedicated branch, commits the changes, and signals
|
|
6
|
+
// completion.
|
|
7
|
+
// Phase 2 (Review): A second sonnet agent reviews the branch diff and either
|
|
8
|
+
// approves it or makes corrections directly on the branch.
|
|
9
|
+
//
|
|
10
|
+
// The outer loop repeats up to MAX_ITERATIONS times, processing one issue per
|
|
11
|
+
// iteration. This is a middle-complexity option between the simple-loop (no review
|
|
12
|
+
// gate) and the parallel-planner (concurrent execution with a planning phase).
|
|
13
|
+
//
|
|
14
|
+
// Usage:
|
|
15
|
+
// npx tsx .sandcastle/main.ts
|
|
16
|
+
// Or add to package.json:
|
|
17
|
+
// "scripts": { "sandcastle": "npx tsx .sandcastle/main.ts" }
|
|
18
|
+
|
|
19
|
+
import * as sandcastle from "@ai-hero/sandcastle";
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Configuration
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
// Maximum number of implement→review cycles to run before stopping.
|
|
26
|
+
// Each cycle works on one issue. Raise this to process more issues per run.
|
|
27
|
+
const MAX_ITERATIONS = 10;
|
|
28
|
+
|
|
29
|
+
// Hooks run inside the sandbox before the agent starts each iteration.
|
|
30
|
+
// npm install ensures the sandbox always has fresh dependencies.
|
|
31
|
+
const hooks = {
|
|
32
|
+
onSandboxReady: [{ command: "npm install" }],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Copy node_modules from the host into the worktree before each sandbox
|
|
36
|
+
// starts. Avoids a full npm install from scratch; the hook above handles
|
|
37
|
+
// platform-specific binaries and any packages added since the last copy.
|
|
38
|
+
const copyToSandbox = ["node_modules"];
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Main loop
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
for (let iteration = 1; iteration <= MAX_ITERATIONS; iteration++) {
|
|
45
|
+
console.log(`\n=== Iteration ${iteration}/${MAX_ITERATIONS} ===\n`);
|
|
46
|
+
|
|
47
|
+
// -------------------------------------------------------------------------
|
|
48
|
+
// Phase 1: Implement
|
|
49
|
+
//
|
|
50
|
+
// A sonnet agent picks the next open GitHub issue, creates a branch, writes
|
|
51
|
+
// the implementation (using RGR: Red → Green → Repeat → Refactor), and
|
|
52
|
+
// commits the result.
|
|
53
|
+
//
|
|
54
|
+
// The agent signals completion via <promise>COMPLETE</promise> when done.
|
|
55
|
+
// The result contains the branch name the agent worked on.
|
|
56
|
+
// -------------------------------------------------------------------------
|
|
57
|
+
const implement = await sandcastle.run({
|
|
58
|
+
hooks,
|
|
59
|
+
copyToSandbox,
|
|
60
|
+
name: "implementer",
|
|
61
|
+
maxIterations: 100,
|
|
62
|
+
model: "claude-sonnet-4-6",
|
|
63
|
+
promptFile: "./.sandcastle/implement-prompt.md",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Extract the branch the agent worked on so the reviewer can target it.
|
|
67
|
+
const branch = implement.branch;
|
|
68
|
+
|
|
69
|
+
if (!implement.commits.length) {
|
|
70
|
+
console.log("Implementation agent made no commits. Skipping review.");
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(`\nImplementation complete on branch: ${branch}`);
|
|
75
|
+
console.log(`Commits: ${implement.commits.length}`);
|
|
76
|
+
|
|
77
|
+
// -------------------------------------------------------------------------
|
|
78
|
+
// Phase 2: Review
|
|
79
|
+
//
|
|
80
|
+
// A second sonnet agent reviews the diff of the branch produced by Phase 1.
|
|
81
|
+
// It uses the {{BRANCH}} prompt argument to inspect the right branch, and
|
|
82
|
+
// either approves or makes corrections directly on the branch.
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
await sandcastle.run({
|
|
85
|
+
hooks,
|
|
86
|
+
copyToSandbox,
|
|
87
|
+
name: "reviewer",
|
|
88
|
+
maxIterations: 10,
|
|
89
|
+
model: "claude-sonnet-4-6",
|
|
90
|
+
promptFile: "./.sandcastle/review-prompt.md",
|
|
91
|
+
// Prompt arguments substitute {{BRANCH}} in review-prompt.md before the
|
|
92
|
+
// agent sees the prompt.
|
|
93
|
+
promptArgs: {
|
|
94
|
+
BRANCH: branch,
|
|
95
|
+
},
|
|
96
|
+
branch,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
console.log("\nReview complete.");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log("\nAll done.");
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# TASK
|
|
2
|
+
|
|
3
|
+
Review the code changes on branch `{{BRANCH}}` and provide actionable feedback.
|
|
4
|
+
|
|
5
|
+
# CONTEXT
|
|
6
|
+
|
|
7
|
+
## Branch diff
|
|
8
|
+
|
|
9
|
+
!`git diff main...{{BRANCH}}`
|
|
10
|
+
|
|
11
|
+
## Commits on this branch
|
|
12
|
+
|
|
13
|
+
!`git log main..{{BRANCH}} --oneline`
|
|
14
|
+
|
|
15
|
+
# REVIEW CHECKLIST
|
|
16
|
+
|
|
17
|
+
Examine the diff above and assess:
|
|
18
|
+
|
|
19
|
+
1. **Correctness** — Does the implementation match the intent of the issue? Are edge cases handled?
|
|
20
|
+
2. **Tests** — Are the new/changed behaviours covered by tests? Do the tests actually exercise the right code paths?
|
|
21
|
+
3. **Code quality** — Is the code clear, minimal, and consistent with the surrounding codebase? No dead code or unnecessary complexity?
|
|
22
|
+
4. **Type safety** — Are there any unsafe casts, `any` types, or unchecked assumptions?
|
|
23
|
+
5. **Security** — Does the change introduce injection vulnerabilities, credential leaks, or other security issues?
|
|
24
|
+
|
|
25
|
+
# OUTPUT
|
|
26
|
+
|
|
27
|
+
If the branch is acceptable:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
REVIEW RESULT: APPROVED
|
|
31
|
+
|
|
32
|
+
<summary of what the implementation does and why it looks good>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If changes are needed, make them directly on the branch, then commit and output:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
REVIEW RESULT: CHANGES MADE
|
|
39
|
+
|
|
40
|
+
<summary of what was changed and why>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Once your review is complete, output <promise>COMPLETE</promise>.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { run } from "@ai-hero/sandcastle";
|
|
2
|
+
|
|
3
|
+
// Simple loop: an agent that picks open GitHub issues one by one and closes them.
|
|
4
|
+
// Run this with: npx tsx .sandcastle/main.ts
|
|
5
|
+
// Or add to package.json scripts: "sandcastle": "npx tsx .sandcastle/main.ts"
|
|
6
|
+
|
|
7
|
+
await run({
|
|
8
|
+
// A name for this run, shown as a prefix in log output.
|
|
9
|
+
name: "worker",
|
|
10
|
+
|
|
11
|
+
// Path to the prompt file. Shell expressions inside are evaluated inside the
|
|
12
|
+
// sandbox at the start of each iteration, so the agent always sees fresh data.
|
|
13
|
+
promptFile: "./.sandcastle/prompt.md",
|
|
14
|
+
|
|
15
|
+
// Maximum number of iterations (agent invocations) to run in a session.
|
|
16
|
+
// Each iteration works on a single issue. Increase this to process more issues
|
|
17
|
+
// per run, or set it to 1 for a single-shot mode.
|
|
18
|
+
maxIterations: 3,
|
|
19
|
+
|
|
20
|
+
// The Claude model to use. Sonnet balances capability and speed for most tasks.
|
|
21
|
+
// Switch to claude-opus-4-6 for harder problems, or claude-haiku-4-5 for speed.
|
|
22
|
+
model: "claude-sonnet-4-6",
|
|
23
|
+
|
|
24
|
+
// Copy node_modules from the host into the worktree before the sandbox
|
|
25
|
+
// starts. This avoids a full npm install from scratch on every iteration.
|
|
26
|
+
// The onSandboxReady hook still runs npm install as a safety net to handle
|
|
27
|
+
// platform-specific binaries and any packages added since the last copy.
|
|
28
|
+
copyToSandbox: ["node_modules"],
|
|
29
|
+
|
|
30
|
+
// Lifecycle hooks — commands that run inside the sandbox at specific points.
|
|
31
|
+
hooks: {
|
|
32
|
+
// onSandboxReady runs once after the sandbox is initialised and the repo is
|
|
33
|
+
// synced in, before the agent starts. Use it to install dependencies or run
|
|
34
|
+
// any other setup steps your project needs.
|
|
35
|
+
onSandboxReady: [{ command: "npm install" }],
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Context
|
|
2
|
+
|
|
3
|
+
## Open issues
|
|
4
|
+
|
|
5
|
+
!`gh issue list --json number,title,body --limit 20`
|
|
6
|
+
|
|
7
|
+
## Recent RALPH commits (last 10)
|
|
8
|
+
|
|
9
|
+
!`git log --oneline --grep="RALPH" -10`
|
|
10
|
+
|
|
11
|
+
# Task
|
|
12
|
+
|
|
13
|
+
You are RALPH — an autonomous coding agent working through GitHub issues one at a time.
|
|
14
|
+
|
|
15
|
+
## Priority order
|
|
16
|
+
|
|
17
|
+
Work on issues in this order:
|
|
18
|
+
|
|
19
|
+
1. **Bug fixes** — broken behaviour affecting users
|
|
20
|
+
2. **Tracer bullets** — thin end-to-end slices that prove an approach works
|
|
21
|
+
3. **Polish** — improving existing functionality (error messages, UX, docs)
|
|
22
|
+
4. **Refactors** — internal cleanups with no user-visible change
|
|
23
|
+
|
|
24
|
+
Pick the highest-priority open issue that is not blocked by another open issue.
|
|
25
|
+
|
|
26
|
+
## Workflow
|
|
27
|
+
|
|
28
|
+
1. **Explore** — read the issue carefully. Pull in the parent PRD if referenced. Read the relevant source files and tests before writing any code.
|
|
29
|
+
2. **Plan** — decide what to change and why. Keep the change as small as possible.
|
|
30
|
+
3. **Execute** — use RGR (Red → Green → Repeat → Refactor): write a failing test first, then write the implementation to pass it.
|
|
31
|
+
4. **Verify** — run `npm run typecheck` and `npm run test` before committing. Fix any failures before proceeding.
|
|
32
|
+
5. **Commit** — make a single git commit. The message MUST:
|
|
33
|
+
- Start with `RALPH:` prefix
|
|
34
|
+
- Include the task completed and any PRD reference
|
|
35
|
+
- List key decisions made
|
|
36
|
+
- List files changed
|
|
37
|
+
- Note any blockers for the next iteration
|
|
38
|
+
6. **Close** — close the issue with `gh issue close <number> --comment "..."` explaining what was done.
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
|
|
42
|
+
- Work on **one issue per iteration**. Do not attempt multiple issues in a single iteration.
|
|
43
|
+
- Do not close an issue until you have committed the fix and verified tests pass.
|
|
44
|
+
- Do not leave commented-out code or TODO comments in committed code.
|
|
45
|
+
- If you are blocked (missing context, failing tests you cannot fix, external dependency), leave a comment on the issue and move on — do not close it.
|
|
46
|
+
|
|
47
|
+
# Done
|
|
48
|
+
|
|
49
|
+
When all actionable issues are complete (or you are blocked on all remaining ones), output the completion signal:
|
|
50
|
+
|
|
51
|
+
<promise>COMPLETE</promise>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,QAyB3B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const SKELETON_PROMPT = `# Context
|
|
2
|
+
|
|
3
|
+
<!-- Use !` +
|
|
4
|
+
"`" +
|
|
5
|
+
`command` +
|
|
6
|
+
"`" +
|
|
7
|
+
` to pull in dynamic context. Commands run inside the sandbox. -->
|
|
8
|
+
<!-- Example: !` +
|
|
9
|
+
"`" +
|
|
10
|
+
`git log --oneline -10` +
|
|
11
|
+
"`" +
|
|
12
|
+
` or !` +
|
|
13
|
+
"`" +
|
|
14
|
+
`gh issue list --json number,title` +
|
|
15
|
+
"`" +
|
|
16
|
+
` -->
|
|
17
|
+
|
|
18
|
+
# Task
|
|
19
|
+
|
|
20
|
+
<!-- Describe what the agent should do. -->
|
|
21
|
+
|
|
22
|
+
# Done
|
|
23
|
+
|
|
24
|
+
<!-- When the task is complete, output <promise>COMPLETE</promise> to signal early termination. -->
|
|
25
|
+
`;
|
|
26
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAC1B;;WAES;IACT,GAAG;IACH,SAAS;IACT,GAAG;IACH;gBACc;IACd,GAAG;IACH,uBAAuB;IACvB,GAAG;IACH,OAAO;IACP,GAAG;IACH,mCAAmC;IACnC,GAAG;IACH;;;;;;;;;CASD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal cleanup for abrupt exits.
|
|
3
|
+
*
|
|
4
|
+
* @clack/prompts' spinner and taskLog call stdin.setRawMode(true) and hide
|
|
5
|
+
* the cursor via escape sequences. When the process is killed by a signal
|
|
6
|
+
* handler that calls process.exit() directly (e.g. during Ctrl-C cleanup in
|
|
7
|
+
* SandboxFactory), clack's own cleanup is bypassed and the terminal is left
|
|
8
|
+
* in raw mode with the cursor hidden.
|
|
9
|
+
*
|
|
10
|
+
* Registering a process 'exit' listener that restores these guarantees the
|
|
11
|
+
* terminal is always left in a usable state.
|
|
12
|
+
*/
|
|
13
|
+
/** Escape sequence to show the cursor (DECTCEM). */
|
|
14
|
+
export declare const SHOW_CURSOR = "\u001B[?25h";
|
|
15
|
+
/**
|
|
16
|
+
* Creates a synchronous exit handler that restores terminal state.
|
|
17
|
+
* Extracted as a pure function so it can be unit-tested without side effects.
|
|
18
|
+
*/
|
|
19
|
+
export declare const makeTerminalCleanupHandler: (stdin: {
|
|
20
|
+
isTTY?: boolean | undefined;
|
|
21
|
+
setRawMode?: ((raw: boolean) => void) | undefined;
|
|
22
|
+
}, stdout: {
|
|
23
|
+
write: (data: string) => boolean;
|
|
24
|
+
}) => () => void;
|
|
25
|
+
/**
|
|
26
|
+
* Registers the terminal cleanup handler on process 'exit'.
|
|
27
|
+
* Call once at program startup (main.ts).
|
|
28
|
+
*/
|
|
29
|
+
export declare const setupTerminalCleanup: () => void;
|
|
30
|
+
//# sourceMappingURL=terminalCleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminalCleanup.d.ts","sourceRoot":"","sources":["../src/terminalCleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,oDAAoD;AACpD,eAAO,MAAM,WAAW,gBAAc,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;gBAcpC,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,oBAAoB,YAEhC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal cleanup for abrupt exits.
|
|
3
|
+
*
|
|
4
|
+
* @clack/prompts' spinner and taskLog call stdin.setRawMode(true) and hide
|
|
5
|
+
* the cursor via escape sequences. When the process is killed by a signal
|
|
6
|
+
* handler that calls process.exit() directly (e.g. during Ctrl-C cleanup in
|
|
7
|
+
* SandboxFactory), clack's own cleanup is bypassed and the terminal is left
|
|
8
|
+
* in raw mode with the cursor hidden.
|
|
9
|
+
*
|
|
10
|
+
* Registering a process 'exit' listener that restores these guarantees the
|
|
11
|
+
* terminal is always left in a usable state.
|
|
12
|
+
*/
|
|
13
|
+
/** Escape sequence to show the cursor (DECTCEM). */
|
|
14
|
+
export const SHOW_CURSOR = "\x1b[?25h";
|
|
15
|
+
/**
|
|
16
|
+
* Creates a synchronous exit handler that restores terminal state.
|
|
17
|
+
* Extracted as a pure function so it can be unit-tested without side effects.
|
|
18
|
+
*/
|
|
19
|
+
export const makeTerminalCleanupHandler = (stdin, stdout) => () => {
|
|
20
|
+
if (stdin.isTTY && stdin.setRawMode) {
|
|
21
|
+
try {
|
|
22
|
+
stdin.setRawMode(false);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Best-effort — may fail if stdin is already closed
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
stdout.write(SHOW_CURSOR);
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Registers the terminal cleanup handler on process 'exit'.
|
|
32
|
+
* Call once at program startup (main.ts).
|
|
33
|
+
*/
|
|
34
|
+
export const setupTerminalCleanup = () => {
|
|
35
|
+
process.on("exit", makeTerminalCleanupHandler(process.stdin, process.stdout));
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=terminalCleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminalCleanup.js","sourceRoot":"","sources":["../src/terminalCleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,oDAAoD;AACpD,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,CACE,KAA+D,EAC/D,MAA4C,EAC5C,EAAE,CACJ,GAAS,EAAE;IACT,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;QACtD,CAAC;IACH,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEJ;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAS,EAAE;IAC7C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,0BAA0B,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helper: creates a local (filesystem-based) Sandbox layer for unit tests.
|
|
3
|
+
* This replaces FilesystemSandbox which has been removed.
|
|
4
|
+
*/
|
|
5
|
+
import { Layer } from "effect";
|
|
6
|
+
import { Sandbox } from "./SandboxFactory.js";
|
|
7
|
+
export declare const makeLocalSandboxLayer: (sandboxDir: string) => Layer.Layer<Sandbox, never, never>;
|
|
8
|
+
//# sourceMappingURL=testSandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testSandbox.d.ts","sourceRoot":"","sources":["../src/testSandbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AAQvC,OAAO,EAAmB,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAa/D,eAAO,MAAM,qBAAqB,4DA8GjC,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helper: creates a local (filesystem-based) Sandbox layer for unit tests.
|
|
3
|
+
* This replaces FilesystemSandbox which has been removed.
|
|
4
|
+
*/
|
|
5
|
+
import { Effect, Layer } from "effect";
|
|
6
|
+
import { execFile, spawn } from "node:child_process";
|
|
7
|
+
import { copyFile, mkdir } from "node:fs/promises";
|
|
8
|
+
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { createInterface } from "node:readline";
|
|
12
|
+
import { CopyError, ExecError } from "./errors.js";
|
|
13
|
+
import { Sandbox } from "./SandboxFactory.js";
|
|
14
|
+
/**
|
|
15
|
+
* Creates an isolated git global config env so that test sandbox
|
|
16
|
+
* `git config --global` writes don't corrupt the developer's real ~/.gitconfig.
|
|
17
|
+
*/
|
|
18
|
+
const createIsolatedGitEnv = () => {
|
|
19
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "test-gitconfig-"));
|
|
20
|
+
const globalConfigPath = join(tmpDir, ".gitconfig");
|
|
21
|
+
writeFileSync(globalConfigPath, "");
|
|
22
|
+
return { GIT_CONFIG_GLOBAL: globalConfigPath };
|
|
23
|
+
};
|
|
24
|
+
export const makeLocalSandboxLayer = (sandboxDir) => {
|
|
25
|
+
const gitEnv = createIsolatedGitEnv();
|
|
26
|
+
const env = { ...process.env, ...gitEnv };
|
|
27
|
+
return Layer.succeed(Sandbox, {
|
|
28
|
+
exec: (command, options) => Effect.async((resume) => {
|
|
29
|
+
execFile("sh", ["-c", command], {
|
|
30
|
+
cwd: options?.cwd ?? sandboxDir,
|
|
31
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
32
|
+
env,
|
|
33
|
+
}, (error, stdout, stderr) => {
|
|
34
|
+
if (error && error.code === undefined) {
|
|
35
|
+
resume(Effect.fail(new ExecError({
|
|
36
|
+
command,
|
|
37
|
+
message: `Failed to exec: ${error.message}`,
|
|
38
|
+
})));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
resume(Effect.succeed({
|
|
42
|
+
stdout: stdout.toString(),
|
|
43
|
+
stderr: stderr.toString(),
|
|
44
|
+
exitCode: typeof error?.code === "number"
|
|
45
|
+
? error.code
|
|
46
|
+
: 0,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}),
|
|
51
|
+
execStreaming: (command, onStdoutLine, options) => Effect.async((resume) => {
|
|
52
|
+
const proc = spawn("sh", ["-c", command], {
|
|
53
|
+
cwd: options?.cwd ?? sandboxDir,
|
|
54
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
55
|
+
env,
|
|
56
|
+
});
|
|
57
|
+
const stdoutChunks = [];
|
|
58
|
+
const stderrChunks = [];
|
|
59
|
+
const rl = createInterface({ input: proc.stdout });
|
|
60
|
+
rl.on("line", (line) => {
|
|
61
|
+
stdoutChunks.push(line);
|
|
62
|
+
onStdoutLine(line);
|
|
63
|
+
});
|
|
64
|
+
proc.stderr.on("data", (chunk) => {
|
|
65
|
+
stderrChunks.push(chunk.toString());
|
|
66
|
+
});
|
|
67
|
+
proc.on("error", (error) => {
|
|
68
|
+
resume(Effect.fail(new ExecError({
|
|
69
|
+
command,
|
|
70
|
+
message: `Failed to exec: ${error.message}`,
|
|
71
|
+
})));
|
|
72
|
+
});
|
|
73
|
+
proc.on("close", (code) => {
|
|
74
|
+
resume(Effect.succeed({
|
|
75
|
+
stdout: stdoutChunks.join("\n"),
|
|
76
|
+
stderr: stderrChunks.join(""),
|
|
77
|
+
exitCode: code ?? 0,
|
|
78
|
+
}));
|
|
79
|
+
});
|
|
80
|
+
}),
|
|
81
|
+
copyIn: (hostPath, sandboxPath) => Effect.tryPromise({
|
|
82
|
+
try: async () => {
|
|
83
|
+
await mkdir(dirname(sandboxPath), { recursive: true });
|
|
84
|
+
await copyFile(hostPath, sandboxPath);
|
|
85
|
+
},
|
|
86
|
+
catch: (e) => new CopyError({
|
|
87
|
+
message: `Failed to copy ${hostPath} -> ${sandboxPath}: ${e}`,
|
|
88
|
+
}),
|
|
89
|
+
}),
|
|
90
|
+
copyOut: (sandboxPath, hostPath) => Effect.tryPromise({
|
|
91
|
+
try: async () => {
|
|
92
|
+
await mkdir(dirname(hostPath), { recursive: true });
|
|
93
|
+
await copyFile(sandboxPath, hostPath);
|
|
94
|
+
},
|
|
95
|
+
catch: (e) => new CopyError({
|
|
96
|
+
message: `Failed to copy ${sandboxPath} -> ${hostPath}: ${e}`,
|
|
97
|
+
}),
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=testSandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testSandbox.js","sourceRoot":"","sources":["../src/testSandbox.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-hero/sandcastle",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "CLI for orchestrating AI agents in isolated sandbox environments",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"sandcastle": "dist/main.js"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsgo --project tsconfig.build.json",
|
|
19
|
+
"postbuild": "rm -rf dist/templates && cp -r src/templates dist/templates",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"typecheck": "tsgo --noEmit",
|
|
23
|
+
"format": "prettier --write .",
|
|
24
|
+
"format:check": "prettier --check .",
|
|
25
|
+
"prepare": "husky",
|
|
26
|
+
"release": "changeset publish",
|
|
27
|
+
"run-sandcastle": "tsx .sandcastle/run.ts"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"cli",
|
|
31
|
+
"sandbox",
|
|
32
|
+
"docker",
|
|
33
|
+
"ai",
|
|
34
|
+
"agent"
|
|
35
|
+
],
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@changesets/cli": "^2.30.0",
|
|
39
|
+
"@effect/vitest": "^0.28.0",
|
|
40
|
+
"@typescript/native-preview": "^7.0.0-dev.20260317.1",
|
|
41
|
+
"husky": "^9.1.7",
|
|
42
|
+
"lint-staged": "^15.5.1",
|
|
43
|
+
"prettier": "^3.5.3",
|
|
44
|
+
"tsx": "^4.21.0",
|
|
45
|
+
"vitest": "^3.2.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@clack/prompts": "^1.1.0",
|
|
49
|
+
"@effect/cli": "^0.74.0",
|
|
50
|
+
"@effect/platform": "^0.95.0",
|
|
51
|
+
"@effect/platform-node": "^0.105.0",
|
|
52
|
+
"@effect/printer": "^0.48.0",
|
|
53
|
+
"@effect/printer-ansi": "^0.48.0",
|
|
54
|
+
"effect": "^3.20.0"
|
|
55
|
+
},
|
|
56
|
+
"lint-staged": {
|
|
57
|
+
"*.{ts,tsx,js,jsx,json,md}": "prettier --write"
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"dist"
|
|
61
|
+
]
|
|
62
|
+
}
|