orcastrator 0.2.7 → 0.2.8
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.
|
@@ -50,7 +50,7 @@ function extractAssistantText(message) {
|
|
|
50
50
|
.trim();
|
|
51
51
|
return text.length > 0 ? text : null;
|
|
52
52
|
}
|
|
53
|
-
function parseTaskArray(raw) {
|
|
53
|
+
export function parseTaskArray(raw) {
|
|
54
54
|
const parsed = JSON.parse(raw);
|
|
55
55
|
if (!Array.isArray(parsed)) {
|
|
56
56
|
throw new Error("Claude plan response was not a JSON array");
|
|
@@ -63,11 +63,18 @@ function parseTaskArray(raw) {
|
|
|
63
63
|
dependencies: Array.isArray(task.dependencies)
|
|
64
64
|
? task.dependencies.map(String)
|
|
65
65
|
: [],
|
|
66
|
+
// Apply sensible defaults for required fields the LLM may have omitted.
|
|
67
|
+
name: typeof task.name === "string" && task.name.length > 0 ? task.name : "Unnamed task",
|
|
68
|
+
description: typeof task.description === "string" ? task.description : "",
|
|
69
|
+
acceptance_criteria: Array.isArray(task.acceptance_criteria) ? task.acceptance_criteria : [],
|
|
70
|
+
status: typeof task.status === "string" && task.status.length > 0 ? task.status : "pending",
|
|
71
|
+
retries: typeof task.retries === "number" ? task.retries : 0,
|
|
72
|
+
maxRetries: typeof task.maxRetries === "number" ? task.maxRetries : 3,
|
|
66
73
|
}));
|
|
67
74
|
}
|
|
68
|
-
function parseTaskExecution(raw) {
|
|
75
|
+
export function parseTaskExecution(raw) {
|
|
69
76
|
const parsed = JSON.parse(raw);
|
|
70
|
-
if (!parsed || typeof parsed !== "object") {
|
|
77
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
71
78
|
throw new Error("Claude task response was not a JSON object");
|
|
72
79
|
}
|
|
73
80
|
const candidate = parsed;
|
|
@@ -112,9 +119,9 @@ async function collectSessionResult(session) {
|
|
|
112
119
|
function getModel(config) {
|
|
113
120
|
return config?.claude?.model ?? process.env.ORCA_CLAUDE_MODEL ?? "claude-sonnet-4-5";
|
|
114
121
|
}
|
|
115
|
-
export async function planSpec(spec, systemContext) {
|
|
122
|
+
export async function planSpec(spec, systemContext, config) {
|
|
116
123
|
const session = unstable_v2_createSession({
|
|
117
|
-
model: getModel()
|
|
124
|
+
model: getModel(config)
|
|
118
125
|
});
|
|
119
126
|
try {
|
|
120
127
|
const streamPromise = collectSessionResult(session);
|
|
@@ -49,6 +49,11 @@ function coerceConfig(candidate) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
if ("executor" in candidate && candidate.executor !== undefined) {
|
|
53
|
+
if (candidate.executor !== "claude" && candidate.executor !== "codex") {
|
|
54
|
+
throw new Error(`Config.executor must be 'claude' or 'codex', got ${String(candidate.executor)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
52
57
|
return candidate;
|
|
53
58
|
}
|
|
54
59
|
export async function loadConfig(configPath) {
|
package/dist/core/planner.js
CHANGED
|
@@ -24,7 +24,7 @@ export async function runPlanner(specPath, store, runId, config) {
|
|
|
24
24
|
const systemContext = skills.length === 0
|
|
25
25
|
? DEFAULT_SYSTEM_CONTEXT
|
|
26
26
|
: `${DEFAULT_SYSTEM_CONTEXT}\n\n${formatSkillsSection(skills)}`;
|
|
27
|
-
const result = await planSpecImpl(spec, systemContext);
|
|
27
|
+
const result = await planSpecImpl(spec, systemContext, config);
|
|
28
28
|
validateDAG(result.tasks);
|
|
29
29
|
await store.writeTasks(runId, result.tasks);
|
|
30
30
|
await store.updateRun(runId, {
|
package/dist/core/task-runner.js
CHANGED
|
@@ -124,11 +124,11 @@ export async function runTaskRunner(options) {
|
|
|
124
124
|
executeTaskFn = claudeAgent.executeTask;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
let run = await store.getRun(runId);
|
|
128
|
-
if (!run) {
|
|
129
|
-
throw new Error(`Run not found: ${runId}`);
|
|
130
|
-
}
|
|
131
127
|
try {
|
|
128
|
+
let run = await store.getRun(runId);
|
|
129
|
+
if (!run) {
|
|
130
|
+
throw new Error(`Run not found: ${runId}`);
|
|
131
|
+
}
|
|
132
132
|
validateDAG(run.tasks);
|
|
133
133
|
await emitHook({
|
|
134
134
|
runId: run.runId,
|
|
@@ -59,7 +59,12 @@ export async function loadSkill(skillDirPath) {
|
|
|
59
59
|
skillFileContent = await readFile(skillFilePath, "utf8");
|
|
60
60
|
}
|
|
61
61
|
catch (error) {
|
|
62
|
-
|
|
62
|
+
const errorCode = error.code;
|
|
63
|
+
if (errorCode === "ENOENT") {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
if (errorCode === "EACCES" || errorCode === "EPERM") {
|
|
67
|
+
console.warn(`Skipping skill at ${expandedDirPath}: unable to read SKILL.md (${errorCode})`);
|
|
63
68
|
return null;
|
|
64
69
|
}
|
|
65
70
|
throw error;
|
|
@@ -87,13 +92,21 @@ export async function loadSkillsFromDir(skillsDirPath) {
|
|
|
87
92
|
throw error;
|
|
88
93
|
}
|
|
89
94
|
const subdirectories = entries
|
|
90
|
-
.filter((entry) =>
|
|
95
|
+
.filter((entry) => {
|
|
96
|
+
if (entry.isSymbolicLink()) {
|
|
97
|
+
console.warn(`Skipping symlinked skill entry: ${path.join(expandedDirPath, entry.name)}`);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return entry.isDirectory();
|
|
101
|
+
})
|
|
91
102
|
.map((entry) => entry.name)
|
|
92
103
|
.sort((a, b) => a.localeCompare(b));
|
|
93
104
|
const loaded = await Promise.all(subdirectories.map((subdirName) => loadSkill(path.join(expandedDirPath, subdirName))));
|
|
94
105
|
return loaded.filter((skill) => skill !== null);
|
|
95
106
|
}
|
|
96
107
|
export async function loadSkills(config) {
|
|
108
|
+
// NOTE: config.skills paths are currently resolved relative to process.cwd().
|
|
109
|
+
// A future improvement can resolve them relative to the config file location.
|
|
97
110
|
const fromConfig = await Promise.all((config?.skills ?? []).map((skillPath) => loadSkill(skillPath)));
|
|
98
111
|
const projectSkills = await loadSkillsFromDir(path.join(process.cwd(), ".orca", "skills"));
|
|
99
112
|
const globalSkills = await loadSkillsFromDir(path.join(os.homedir(), ".orca", "skills"));
|