jules-orchestrator-kit 0.7.0 → 0.8.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/package.json +1 -1
- package/scripts/command-resolver.mjs +25 -7
- package/scripts/jules-status.mjs +32 -15
- package/scripts/jules-swarm.mjs +2 -2
- package/scripts/utils.mjs +18 -16
package/package.json
CHANGED
|
@@ -44,6 +44,23 @@ export function resolveProjectCommands(projectRoot = process.cwd()) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function detectPackageManager(root, pkg = {}) {
|
|
48
|
+
if (fs.existsSync(path.join(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
49
|
+
if (fs.existsSync(path.join(root, "yarn.lock"))) return "yarn";
|
|
50
|
+
if (fs.existsSync(path.join(root, "bun.lockb"))) return "bun";
|
|
51
|
+
if (fs.existsSync(path.join(root, "package-lock.json"))) return "npm";
|
|
52
|
+
|
|
53
|
+
const pm = pkg.packageManager;
|
|
54
|
+
if (typeof pm === "string") {
|
|
55
|
+
if (pm.startsWith("pnpm")) return "pnpm";
|
|
56
|
+
if (pm.startsWith("yarn")) return "yarn";
|
|
57
|
+
if (pm.startsWith("bun")) return "bun";
|
|
58
|
+
if (pm.startsWith("npm")) return "npm";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return "npm";
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
// 2. Dynamic Detector Strategy List
|
|
48
65
|
const detectors = [
|
|
49
66
|
{
|
|
@@ -59,20 +76,21 @@ export function resolveProjectCommands(projectRoot = process.cwd()) {
|
|
|
59
76
|
resolve: (root) => {
|
|
60
77
|
try {
|
|
61
78
|
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
|
|
79
|
+
const pm = detectPackageManager(root, pkg);
|
|
62
80
|
const scripts = pkg.scripts || {};
|
|
63
|
-
let verifyScript = scripts["check:all"] ?
|
|
81
|
+
let verifyScript = scripts["check:all"] ? `${pm} run check:all` : "";
|
|
64
82
|
if (!verifyScript) {
|
|
65
83
|
const parts = [];
|
|
66
|
-
if (scripts.lint) parts.push(
|
|
67
|
-
else if (scripts.check) parts.push(
|
|
68
|
-
if (scripts.test) parts.push(
|
|
84
|
+
if (scripts.lint) parts.push(`${pm} run lint`);
|
|
85
|
+
else if (scripts.check) parts.push(`${pm} run check`);
|
|
86
|
+
if (scripts.test) parts.push(`${pm} test`);
|
|
69
87
|
verifyScript = parts.join(" && ");
|
|
70
88
|
}
|
|
71
|
-
const buildScript = scripts.build ?
|
|
89
|
+
const buildScript = scripts.build ? `${pm} run build` : "";
|
|
72
90
|
return {
|
|
73
|
-
testCmd: verifyScript ||
|
|
91
|
+
testCmd: verifyScript || `${pm} test`,
|
|
74
92
|
buildCmd: buildScript,
|
|
75
|
-
source:
|
|
93
|
+
source: `package.json (${pm})`,
|
|
76
94
|
};
|
|
77
95
|
} catch (err) {
|
|
78
96
|
console.warn("⚠️ Failed to parse package.json:", err.message);
|
package/scripts/jules-status.mjs
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Jules Task Status Utility
|
|
4
|
-
* Parses the queue.jsonl file and renders a clean console.table
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
1
|
import fs from "node:fs";
|
|
8
2
|
import path from "node:path";
|
|
9
|
-
import { log } from "./utils.mjs";
|
|
3
|
+
import { log, checkDailyBudget } from "./utils.mjs";
|
|
10
4
|
|
|
5
|
+
const isJson = process.argv.includes("--json");
|
|
11
6
|
const queueLogPath = path.resolve(process.cwd(), ".agent/jules-queue/queue.jsonl");
|
|
12
7
|
|
|
8
|
+
const budgetInfo = checkDailyBudget();
|
|
9
|
+
|
|
13
10
|
if (!fs.existsSync(queueLogPath)) {
|
|
14
|
-
|
|
11
|
+
if (isJson) {
|
|
12
|
+
console.log(JSON.stringify({ queue: [], budget: budgetInfo }, null, 2));
|
|
13
|
+
} else {
|
|
14
|
+
log.info("Queue log is empty. No tasks have been dispatched yet.");
|
|
15
|
+
}
|
|
15
16
|
process.exit(0);
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -20,7 +21,11 @@ try {
|
|
|
20
21
|
const lines = content.split("\n").filter(Boolean);
|
|
21
22
|
|
|
22
23
|
if (lines.length === 0) {
|
|
23
|
-
|
|
24
|
+
if (isJson) {
|
|
25
|
+
console.log(JSON.stringify({ queue: [], budget: budgetInfo }, null, 2));
|
|
26
|
+
} else {
|
|
27
|
+
log.info("Queue log is empty.");
|
|
28
|
+
}
|
|
24
29
|
process.exit(0);
|
|
25
30
|
}
|
|
26
31
|
|
|
@@ -32,10 +37,11 @@ try {
|
|
|
32
37
|
const entry = JSON.parse(line);
|
|
33
38
|
if (entry.file) {
|
|
34
39
|
statusMap.set(entry.file, {
|
|
40
|
+
file: entry.file,
|
|
35
41
|
Task: entry.file.replace(/^TASK-\d+-/, "").replace(/\.md$/, ""),
|
|
36
42
|
Status: entry.status,
|
|
37
|
-
Timestamp:
|
|
38
|
-
Error: entry.error ||
|
|
43
|
+
Timestamp: entry.timestamp,
|
|
44
|
+
Error: entry.error || null
|
|
39
45
|
});
|
|
40
46
|
}
|
|
41
47
|
} catch (e) {
|
|
@@ -43,15 +49,26 @@ try {
|
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
|
|
52
|
+
const tasksList = Array.from(statusMap.values());
|
|
53
|
+
|
|
54
|
+
if (isJson) {
|
|
55
|
+
console.log(JSON.stringify({ queue: tasksList, budget: budgetInfo }, null, 2));
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (tasksList.length === 0) {
|
|
47
60
|
log.info("No parseable task events found in queue.jsonl");
|
|
48
61
|
process.exit(0);
|
|
49
62
|
}
|
|
50
63
|
|
|
51
|
-
log.header(
|
|
52
|
-
console.table(
|
|
64
|
+
log.header(`JULES QUEUE STATUS (Budget: ${budgetInfo.used}/${budgetInfo.budget} sessions used)`);
|
|
65
|
+
console.table(tasksList.map(t => ({ Task: t.Task, Status: t.Status, Timestamp: new Date(t.Timestamp).toLocaleString(), Error: t.Error || "-" })));
|
|
53
66
|
|
|
54
67
|
} catch (err) {
|
|
55
|
-
|
|
68
|
+
if (isJson) {
|
|
69
|
+
console.log(JSON.stringify({ error: err.message }, null, 2));
|
|
70
|
+
} else {
|
|
71
|
+
log.error(`Failed to read queue log: ${err.message}`);
|
|
72
|
+
}
|
|
56
73
|
process.exit(1);
|
|
57
74
|
}
|
package/scripts/jules-swarm.mjs
CHANGED
|
@@ -194,8 +194,8 @@ async function runSwarm() {
|
|
|
194
194
|
env: {
|
|
195
195
|
...process.env,
|
|
196
196
|
JULES_PROJECT_ROOT: process.env.JULES_PROJECT_ROOT,
|
|
197
|
-
JULES_SLOT_INDEX: String(
|
|
198
|
-
JULES_SLOT_TOTAL: String(
|
|
197
|
+
JULES_SLOT_INDEX: String(taskNum),
|
|
198
|
+
JULES_SLOT_TOTAL: String(tasks.length)
|
|
199
199
|
},
|
|
200
200
|
});
|
|
201
201
|
if (stdout) log.dim(stdout.trim());
|
package/scripts/utils.mjs
CHANGED
|
@@ -165,10 +165,15 @@ export function redactSecrets(text) {
|
|
|
165
165
|
return sanitized;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
export function
|
|
169
|
-
const
|
|
168
|
+
export function getDailyLedgerPath(ledgerName = "sessions") {
|
|
169
|
+
const dateStr = new Date().toISOString().split("T")[0];
|
|
170
|
+
const stateDir = path.resolve(process.env.JULES_PROJECT_ROOT || process.cwd(), ".agent/state", ledgerName);
|
|
170
171
|
ensureDir(stateDir);
|
|
171
|
-
|
|
172
|
+
return path.join(stateDir, `${dateStr}.jsonl`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function appendLedger(ledgerName, payload) {
|
|
176
|
+
const ledgerPath = getDailyLedgerPath(ledgerName);
|
|
172
177
|
const entry = JSON.stringify({
|
|
173
178
|
timestamp: new Date().toISOString(),
|
|
174
179
|
...payload
|
|
@@ -179,33 +184,30 @@ export function appendLedger(ledgerName, payload) {
|
|
|
179
184
|
|
|
180
185
|
export function checkDailyBudget(maxSessions = 300) {
|
|
181
186
|
const dateStr = new Date().toISOString().split("T")[0];
|
|
182
|
-
const
|
|
183
|
-
const sessionsLedger = path.join(stateDir, "sessions.jsonl");
|
|
187
|
+
const ledgerPath = getDailyLedgerPath("sessions");
|
|
184
188
|
|
|
185
|
-
if (!fs.existsSync(
|
|
189
|
+
if (!fs.existsSync(ledgerPath)) {
|
|
186
190
|
return { ok: true, used: 0, budget: maxSessions };
|
|
187
191
|
}
|
|
188
192
|
|
|
189
|
-
const content = fs.readFileSync(
|
|
193
|
+
const content = fs.readFileSync(ledgerPath, "utf-8");
|
|
190
194
|
const lines = content.split("\n").filter(Boolean);
|
|
191
195
|
|
|
192
196
|
let usedToday = 0;
|
|
193
197
|
for (const line of lines) {
|
|
194
198
|
try {
|
|
195
199
|
const entry = JSON.parse(line);
|
|
196
|
-
if (
|
|
197
|
-
entry.timestamp &&
|
|
198
|
-
entry.timestamp.startsWith(dateStr) &&
|
|
199
|
-
(entry.event === "budget_reserved" || !entry.event)
|
|
200
|
-
) {
|
|
200
|
+
if (entry.event === "budget_reserved" || !entry.event) {
|
|
201
201
|
usedToday++;
|
|
202
202
|
}
|
|
203
|
-
} catch (
|
|
204
|
-
// Ignore
|
|
205
|
-
}
|
|
203
|
+
} catch (_) {}
|
|
206
204
|
}
|
|
207
205
|
|
|
208
|
-
return {
|
|
206
|
+
return {
|
|
207
|
+
ok: usedToday < maxSessions,
|
|
208
|
+
used: usedToday,
|
|
209
|
+
budget: maxSessions
|
|
210
|
+
};
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
function sleepSync(ms) {
|