jules-orchestrator-kit 0.27.0 → 0.28.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/src/provider.mjs CHANGED
@@ -3,15 +3,20 @@ import { spawnSync } from "node:child_process";
3
3
  export const JULES_PRESET = {
4
4
  name: "jules",
5
5
  type: "http",
6
- url: "https://jules.googleapis.com/v1/projects/{project}/sessions",
6
+ url: "https://jules.googleapis.com/v1alpha/sessions",
7
7
  headers: {
8
- "Authorization": "Bearer {token}",
8
+ "X-Goog-Api-Key": "{token}",
9
9
  "Content-Type": "application/json",
10
10
  },
11
11
  bodyTemplate: {
12
- prompt: "{prompt}",
13
12
  title: "{title}",
14
- branch: "{branch}",
13
+ prompt: "{prompt}",
14
+ sourceContext: {
15
+ source: "{source}",
16
+ githubRepoContext: {
17
+ startingBranch: "{branch}",
18
+ },
19
+ },
15
20
  },
16
21
  };
17
22
 
@@ -31,6 +36,14 @@ export const CODEX_PRESET = {
31
36
  promptViaStdin: false,
32
37
  };
33
38
 
39
+ export class MissingApiKeyError extends Error {
40
+ constructor(message = "JULES_API_KEY environment variable is required for Google Jules API dispatch.") {
41
+ super(message);
42
+ this.name = "MissingApiKeyError";
43
+ this.status = 401;
44
+ }
45
+ }
46
+
34
47
  export class ProviderRateLimitError extends Error {
35
48
  constructor(message, opts = {}) {
36
49
  super(message);
@@ -92,6 +105,9 @@ function interpolateDeep(node, data) {
92
105
  * Creates an HTTP or Exec provider adapter based on spec/config.
93
106
  */
94
107
  export function createProvider(spec = "jules", config = {}) {
108
+ if (spec && typeof spec === "object" && typeof spec.dispatch === "function") {
109
+ return spec;
110
+ }
95
111
  const providerSpec = typeof spec === "string"
96
112
  ? (spec === "claude-code" ? CLAUDE_PRESET : spec === "codex" ? CODEX_PRESET : JULES_PRESET)
97
113
  : spec;
@@ -100,11 +116,21 @@ export function createProvider(spec = "jules", config = {}) {
100
116
  name: providerSpec.name || "custom-provider",
101
117
 
102
118
  async dispatch(task, ctx = {}) {
103
- const rawToken = process.env.JULES_API_KEY || process.env.GEMINI_API_KEY || "";
119
+ const rawToken = process.env.JULES_API_KEY || (ctx.allowLegacyKey ? process.env.GEMINI_API_KEY : "") || "";
120
+ if (!rawToken && !ctx.dryRun && providerSpec.name === "jules") {
121
+ throw new MissingApiKeyError();
122
+ }
123
+
124
+ const rawRepo = task.source || ctx.source || process.env.JULES_REPO || "";
125
+ const sourceName = rawRepo
126
+ ? (rawRepo.startsWith("sources/") ? rawRepo : `sources/github/${rawRepo}`)
127
+ : "sources/github/default/repo";
128
+
104
129
  const data = {
105
130
  prompt: task.prompt || "",
106
131
  title: task.title || "Agent Task",
107
132
  branch: task.branch || (config.branchPrefix ? config.branchPrefix + "task" : "agent/task"),
133
+ source: sourceName,
108
134
  project: process.env.JULES_PROJECT_ID || "default",
109
135
  ...ctx,
110
136
  };
@@ -135,19 +161,25 @@ export function createProvider(spec = "jules", config = {}) {
135
161
  }
136
162
 
137
163
  let body;
164
+ let bodyObj;
138
165
  if (typeof providerSpec.bodyTemplate === "string") {
139
166
  try {
140
167
  const parsedObj = JSON.parse(providerSpec.bodyTemplate);
141
- const interpolatedObj = interpolateDeep(parsedObj, data);
142
- body = JSON.stringify(interpolatedObj);
168
+ bodyObj = interpolateDeep(parsedObj, data);
143
169
  } catch (_) {
144
170
  body = interpolateString(providerSpec.bodyTemplate, data);
145
171
  }
146
172
  } else if (providerSpec.bodyTemplate) {
147
- const interpolatedObj = interpolateDeep(providerSpec.bodyTemplate, data);
148
- body = JSON.stringify(interpolatedObj);
173
+ bodyObj = interpolateDeep(providerSpec.bodyTemplate, data);
149
174
  } else {
150
- body = JSON.stringify(data);
175
+ bodyObj = { ...data };
176
+ }
177
+
178
+ if (bodyObj && typeof bodyObj === "object") {
179
+ if (data.repoless || ctx.repoless || task.repoless) {
180
+ delete bodyObj.sourceContext;
181
+ }
182
+ body = JSON.stringify(bodyObj);
151
183
  }
152
184
 
153
185
  const timeoutMs = ctx.timeoutMs || config.timeoutMs || providerSpec.timeoutMs || 120_000;
@@ -1,80 +0,0 @@
1
- import { spawn } from "node:child_process";
2
-
3
- /**
4
- * ProcessGroupManager manages child processes in isolated process groups
5
- * and ensures 100% leak-free cleanup on process exit or termination signals.
6
- */
7
- export class ProcessGroupManager {
8
- constructor() {
9
- this.activePgids = new Set();
10
- this.activePids = new Set();
11
- this.installed = false;
12
- this.installSignalHandlers();
13
- }
14
-
15
- installSignalHandlers() {
16
- if (this.installed) return;
17
- this.installed = true;
18
-
19
- const cleanup = (signal) => {
20
- this.killAll(signal || "SIGTERM");
21
- };
22
-
23
- process.once("SIGINT", () => {
24
- cleanup("SIGINT");
25
- process.exit(130);
26
- });
27
-
28
- process.once("SIGTERM", () => {
29
- cleanup("SIGTERM");
30
- process.exit(143);
31
- });
32
-
33
- process.once("exit", () => {
34
- this.killAll("SIGKILL");
35
- });
36
- }
37
-
38
- spawnProcess(command, args = [], options = {}) {
39
- const opts = {
40
- ...options,
41
- detached: true,
42
- };
43
-
44
- const child = spawn(command, args, opts);
45
-
46
- if (child.pid) {
47
- const pgid = child.pid;
48
- this.activePgids.add(pgid);
49
- this.activePids.add(child.pid);
50
-
51
- child.on("exit", () => {
52
- this.activePgids.delete(pgid);
53
- this.activePids.delete(child.pid);
54
- });
55
-
56
- child.on("error", () => {
57
- this.activePgids.delete(pgid);
58
- this.activePids.delete(child.pid);
59
- });
60
- }
61
-
62
- return child;
63
- }
64
-
65
- killAll(signal = "SIGTERM") {
66
- for (const pgid of this.activePgids) {
67
- try {
68
- process.kill(-pgid, signal);
69
- } catch (_) {
70
- try {
71
- process.kill(pgid, signal);
72
- } catch (_) {}
73
- }
74
- }
75
- this.activePgids.clear();
76
- this.activePids.clear();
77
- }
78
- }
79
-
80
- export const processGroupManager = new ProcessGroupManager();