orcastrator 0.2.13 → 0.2.14
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 +1 -1
- package/dist/cli/commands/setup.js +2 -4
- package/dist/core/planner.js +72 -4
- package/dist/hooks/adapters/stdout.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -188,7 +188,7 @@ Global:
|
|
|
188
188
|
|
|
189
189
|
- `--anthropic-key <key>`
|
|
190
190
|
- `--openai-key <key>`
|
|
191
|
-
- `--check` (API key lookup order: CLI flag → process env → `~/.openclaw/openclaw.json` `env.vars` → `~/.claude/.env` → `~/.config/claude/.env`
|
|
191
|
+
- `--check` (API key lookup order: CLI flag → process env → `~/.openclaw/openclaw.json` `env.vars` → `~/.claude/.env` → `~/.config/claude/.env`)
|
|
192
192
|
- `--global`
|
|
193
193
|
- `--project`
|
|
194
194
|
|
|
@@ -57,7 +57,7 @@ export function resolveApiKey(flagValue, envVarName, openclawConfigPathOrOptions
|
|
|
57
57
|
return envValue.trim();
|
|
58
58
|
}
|
|
59
59
|
const options = typeof openclawConfigPathOrOptions === "string"
|
|
60
|
-
? { ...
|
|
60
|
+
? { ...maybeOptions, openclawConfigPath: openclawConfigPathOrOptions }
|
|
61
61
|
: (openclawConfigPathOrOptions ?? {});
|
|
62
62
|
const homedir = options.homedir ?? os.homedir();
|
|
63
63
|
const openclawValue = readOpenclawEnvVar(envVarName, options.openclawConfigPath, homedir);
|
|
@@ -65,7 +65,6 @@ export function resolveApiKey(flagValue, envVarName, openclawConfigPathOrOptions
|
|
|
65
65
|
return openclawValue;
|
|
66
66
|
}
|
|
67
67
|
const dotenvValue = readDotEnvFallback(envVarName, {
|
|
68
|
-
cwd: options.cwd ?? process.cwd(),
|
|
69
68
|
homedir
|
|
70
69
|
});
|
|
71
70
|
if (dotenvValue) {
|
|
@@ -104,8 +103,7 @@ function readOpenclawEnvVar(envVarName, openclawConfigPath, homedir = os.homedir
|
|
|
104
103
|
function readDotEnvFallback(envVarName, options) {
|
|
105
104
|
const candidatePaths = [
|
|
106
105
|
path.join(options.homedir, ".claude", ".env"),
|
|
107
|
-
path.join(options.homedir, ".config", "claude", ".env")
|
|
108
|
-
path.join(options.cwd, ".env")
|
|
106
|
+
path.join(options.homedir, ".config", "claude", ".env")
|
|
109
107
|
];
|
|
110
108
|
for (const candidatePath of candidatePaths) {
|
|
111
109
|
const value = readEnvVarFromDotEnvFile(candidatePath, envVarName);
|
package/dist/core/planner.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
import { planSpec as planSpecWithClaude } from "../agents/claude/session.js";
|
|
3
4
|
import { planSpec as planSpecWithCodex } from "../agents/codex/session.js";
|
|
4
5
|
import { logger } from "../utils/logger.js";
|
|
5
6
|
import { loadSkills } from "../utils/skill-loader.js";
|
|
6
7
|
import { validateDAG } from "./dependency-graph.js";
|
|
7
8
|
const DEFAULT_SYSTEM_CONTEXT = "You are Orca planner.";
|
|
9
|
+
const PROJECT_INSTRUCTION_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
10
|
+
const PROJECT_INSTRUCTION_CHAR_CAP = 4_000;
|
|
8
11
|
let testPlanSpecOverride = null;
|
|
9
12
|
export function setPlanSpecForTests(fn) {
|
|
10
13
|
testPlanSpecOverride = fn;
|
|
@@ -26,12 +29,77 @@ function formatSkillsSection(skills) {
|
|
|
26
29
|
].join("\n"));
|
|
27
30
|
return ["## Available Skills", "", ...formattedSkills].join("\n");
|
|
28
31
|
}
|
|
32
|
+
async function pathExists(targetPath) {
|
|
33
|
+
try {
|
|
34
|
+
await fs.access(targetPath);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function resolveProjectContextDir(specPath) {
|
|
42
|
+
let currentDir = path.dirname(path.resolve(specPath));
|
|
43
|
+
while (true) {
|
|
44
|
+
const gitMarker = path.join(currentDir, ".git");
|
|
45
|
+
if (await pathExists(gitMarker)) {
|
|
46
|
+
return currentDir;
|
|
47
|
+
}
|
|
48
|
+
const parent = path.dirname(currentDir);
|
|
49
|
+
if (parent === currentDir) {
|
|
50
|
+
return path.dirname(path.resolve(specPath));
|
|
51
|
+
}
|
|
52
|
+
currentDir = parent;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function loadProjectInstructions(specPath) {
|
|
56
|
+
const projectDir = await resolveProjectContextDir(specPath);
|
|
57
|
+
const instructions = [];
|
|
58
|
+
for (const fileName of PROJECT_INSTRUCTION_FILES) {
|
|
59
|
+
const filePath = path.join(projectDir, fileName);
|
|
60
|
+
if (!(await pathExists(filePath))) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const rawContent = await fs.readFile(filePath, "utf8");
|
|
64
|
+
const content = rawContent.slice(0, PROJECT_INSTRUCTION_CHAR_CAP);
|
|
65
|
+
instructions.push({
|
|
66
|
+
fileName,
|
|
67
|
+
filePath,
|
|
68
|
+
content,
|
|
69
|
+
truncated: rawContent.length > PROJECT_INSTRUCTION_CHAR_CAP
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return instructions;
|
|
73
|
+
}
|
|
74
|
+
function formatProjectInstructionsSection(instructions) {
|
|
75
|
+
const parts = ["## Project Instructions"];
|
|
76
|
+
for (const instruction of instructions) {
|
|
77
|
+
parts.push("");
|
|
78
|
+
parts.push(`### ${instruction.fileName} (${instruction.filePath})`);
|
|
79
|
+
parts.push("");
|
|
80
|
+
parts.push("```md");
|
|
81
|
+
parts.push(instruction.content);
|
|
82
|
+
parts.push("```");
|
|
83
|
+
if (instruction.truncated) {
|
|
84
|
+
parts.push(`(truncated to ${PROJECT_INSTRUCTION_CHAR_CAP} characters)`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return parts.join("\n");
|
|
88
|
+
}
|
|
89
|
+
function buildSystemContext(skills, instructions) {
|
|
90
|
+
const sections = [DEFAULT_SYSTEM_CONTEXT];
|
|
91
|
+
if (instructions.length > 0) {
|
|
92
|
+
sections.push(formatProjectInstructionsSection(instructions));
|
|
93
|
+
}
|
|
94
|
+
if (skills.length > 0) {
|
|
95
|
+
sections.push(formatSkillsSection(skills));
|
|
96
|
+
}
|
|
97
|
+
return sections.join("\n\n");
|
|
98
|
+
}
|
|
29
99
|
export async function runPlanner(specPath, store, runId, config) {
|
|
30
100
|
const spec = await fs.readFile(specPath, "utf8");
|
|
31
|
-
const skills = await loadSkills(config);
|
|
32
|
-
const systemContext = skills
|
|
33
|
-
? DEFAULT_SYSTEM_CONTEXT
|
|
34
|
-
: `${DEFAULT_SYSTEM_CONTEXT}\n\n${formatSkillsSection(skills)}`;
|
|
101
|
+
const [skills, instructions] = await Promise.all([loadSkills(config), loadProjectInstructions(specPath)]);
|
|
102
|
+
const systemContext = buildSystemContext(skills, instructions);
|
|
35
103
|
const planSpecImpl = resolvePlanSpecImpl(config);
|
|
36
104
|
const result = await planSpecImpl(spec, systemContext, config);
|
|
37
105
|
validateDAG(result.tasks);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function createStdoutHookHandler(prefix = "[hook]") {
|
|
1
|
+
export function createStdoutHookHandler(prefix = "[hook]", write = console.log) {
|
|
2
2
|
return async (event) => {
|
|
3
3
|
const line = {
|
|
4
4
|
prefix,
|
|
@@ -10,6 +10,6 @@ export function createStdoutHookHandler(prefix = "[hook]") {
|
|
|
10
10
|
error: event.error,
|
|
11
11
|
metadata: event.metadata
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
write(JSON.stringify(line));
|
|
14
14
|
};
|
|
15
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orcastrator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"orca": "dist/cli/index.js"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dev": "bun run src/cli/index.ts",
|
|
11
11
|
"lint": "oxlint src/",
|
|
12
12
|
"typecheck": "tsc --noEmit",
|
|
13
|
-
"test": "bun test",
|
|
13
|
+
"test": "bun test src",
|
|
14
14
|
"start": "bun run src/cli/index.ts",
|
|
15
15
|
"prepare": "husky",
|
|
16
16
|
"postbuild": "chmod +x dist/cli/index.js"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@ratley/codex-client": "^0.1.3",
|
|
22
22
|
"chalk": "^5.3.0",
|
|
23
23
|
"commander": "^13.1.0",
|
|
24
|
-
"zod": "^3.
|
|
24
|
+
"zod": "^4.3.6"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/bun": "^1.2.21",
|