jules-orchestrator-kit 0.51.0 → 0.52.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.
@@ -141,10 +141,23 @@ export const COMMAND_REGISTRY = [
141
141
  "agentctl task create --interactive",
142
142
  ],
143
143
  flags: [
144
- { name: "title", type: "string", description: "Short title for task" },
145
- { name: "prompt", type: "string", description: "Detailed task instructions" },
146
- { name: "verify-cmd", type: "string", description: "Verification command" },
147
- { name: "interactive", type: "boolean", description: "Launch interactive task wizard" },
144
+ { name: "title", type: "string", description: "Short title for task (-t)" },
145
+ { name: "prompt", type: "string", description: "Detailed task instructions (-p)" },
146
+ { name: "prompt-file", type: "string", description: "Read prompt from file (-f)" },
147
+ { name: "role", type: "string", description: "Specialist role (overseer, bolt, sentinel, janitor, a11y, scribe, spectator, alchemist) (-r)" },
148
+ { name: "tier", type: "string", description: "Execution tier override (fast | complex)" },
149
+ { name: "template", type: "string", description: "Task template preset ID" },
150
+ { name: "depends-on", type: "string", description: "Comma-separated task dependency IDs" },
151
+ { name: "verify-cmd", type: "string", description: "Verification command override (-v)" },
152
+ { name: "auto-pr", type: "boolean", description: "Automatically create GitHub PR upon completion" },
153
+ { name: "require-plan-approval", type: "boolean", description: "Require approval of agent plan before execution" },
154
+ { name: "repoless", type: "boolean", description: "Execute in repoless sandbox mode" },
155
+ { name: "interactive", type: "boolean", description: "Launch interactive task wizard (-i)" },
156
+ { name: "non-interactive", type: "boolean", description: "Bypass interactive prompts and use CLI flags" },
157
+ { name: "no-interactive", type: "boolean", description: "Alias for --non-interactive" },
158
+ { name: "yes", type: "boolean", description: "Accept default values non-interactively (-y)" },
159
+ { name: "dry-run", type: "boolean", description: "Simulate task envelope creation without queueing (-d)" },
160
+ { name: "json", type: "boolean", description: "Output structured JSON envelope (-j)" },
148
161
  ],
149
162
  },
150
163
  {
@@ -187,9 +200,14 @@ export const COMMAND_REGISTRY = [
187
200
  "agentctl init --tier pro --yes",
188
201
  ],
189
202
  flags: [
190
- { name: "tier", type: "string", description: "Target configuration tier (free, pro, ultra, enterprise)" },
191
- { name: "interactive", type: "boolean", description: "Launch interactive onboarding wizard" },
192
- { name: "yes", type: "boolean", description: "Accept auto-detected Stack Oracle defaults" },
203
+ { name: "tier", type: "string", description: "Target configuration tier (free, pro, ultra, enterprise) (-t)" },
204
+ { name: "interactive", type: "boolean", description: "Launch interactive onboarding wizard (-i)" },
205
+ { name: "non-interactive", type: "boolean", description: "Run non-interactively with defaults" },
206
+ { name: "no-interactive", type: "boolean", description: "Alias for --non-interactive" },
207
+ { name: "yes", type: "boolean", description: "Accept auto-detected Stack Oracle defaults (-y)" },
208
+ { name: "force", type: "boolean", description: "Force overwrite existing config and assets (-f)" },
209
+ { name: "dry-run", type: "boolean", description: "Preview plan without writing files (-d)" },
210
+ { name: "json", type: "boolean", description: "Output structured JSON manifest (-j)" },
193
211
  ],
194
212
  },
195
213
  {
@@ -333,6 +351,185 @@ export const COMMAND_REGISTRY = [
333
351
  { name: "limit", type: "string", description: "Maximum handovers to list" },
334
352
  ],
335
353
  },
354
+ {
355
+ id: "mutate",
356
+ path: ["mutate"],
357
+ title: "mutate",
358
+ description: "Run zero-dependency diff mutation testing harness",
359
+ category: "Inspect",
360
+ mutates: false,
361
+ risk: "low",
362
+ interactive: "never",
363
+ requiresRepository: true,
364
+ shortcuts: ["mutation"],
365
+ examples: [
366
+ "agentctl mutate",
367
+ "agentctl mutate --min-score 80",
368
+ 'agentctl mutate --max-mutants 20 --test-cmd "npm test"',
369
+ ],
370
+ flags: [
371
+ { name: "min-score", type: "string", description: "Target minimum mutation score threshold (0-100)" },
372
+ { name: "max-mutants", type: "string", description: "Maximum number of mutants to generate and test" },
373
+ { name: "test-cmd", type: "string", description: "Test command override" },
374
+ { name: "verify-cmd", type: "string", description: "Alias for test-cmd" },
375
+ { name: "tier", type: "string", description: "Execution tier (fast | complex)" },
376
+ { name: "dry-run", type: "boolean", description: "Simulate mutation analysis without executing tests (-d)" },
377
+ { name: "json", type: "boolean", description: "Output structured JSON mutation report (-j)" },
378
+ ],
379
+ },
380
+ {
381
+ id: "coverage",
382
+ path: ["coverage"],
383
+ title: "coverage",
384
+ description: "Run native zero-dependency V8 diff coverage check",
385
+ category: "Inspect",
386
+ mutates: false,
387
+ risk: "low",
388
+ interactive: "never",
389
+ requiresRepository: true,
390
+ shortcuts: ["cov"],
391
+ examples: [
392
+ "agentctl coverage",
393
+ "agentctl coverage --min 80",
394
+ 'agentctl coverage --cmd "node --test"',
395
+ ],
396
+ flags: [
397
+ { name: "min", type: "string", description: "Minimum diff line coverage percentage required" },
398
+ { name: "cmd", type: "string", description: "Test command override to run with V8 coverage" },
399
+ { name: "test-cmd", type: "string", description: "Alias for cmd" },
400
+ { name: "verify-cmd", type: "string", description: "Alias for cmd" },
401
+ { name: "dry-run", type: "boolean", description: "Simulate coverage collection without running (-d)" },
402
+ { name: "json", type: "boolean", description: "Output structured JSON coverage report (-j)" },
403
+ ],
404
+ },
405
+ {
406
+ id: "gate",
407
+ path: ["gate"],
408
+ title: "gate",
409
+ description: "Run CI security, rules, and stack verification gate",
410
+ category: "Inspect",
411
+ mutates: false,
412
+ risk: "low",
413
+ interactive: "never",
414
+ requiresRepository: true,
415
+ shortcuts: ["audit", "check"],
416
+ examples: [
417
+ "agentctl gate",
418
+ "agentctl gate --mode working-tree",
419
+ "agentctl gate --fix",
420
+ "agentctl gate --json",
421
+ ],
422
+ flags: [
423
+ { name: "mode", type: "string", description: "Evaluation mode (working-tree | committed | staged) (-m)" },
424
+ { name: "tier", type: "string", description: "Enforce specific tier policies (free | pro | ultra | enterprise)" },
425
+ { name: "allow-protected", type: "boolean", description: "Bypass protected path checks for authorized maintainers" },
426
+ { name: "fix", type: "boolean", description: "Trigger automated OODA self-repair loop on failure" },
427
+ { name: "strict-locks", type: "boolean", description: "Enforce strict anti-tampering verification on test files" },
428
+ { name: "dry-run", type: "boolean", description: "Simulate gate evaluation without persisting evidence (-d)" },
429
+ { name: "json", type: "boolean", description: "Output structured JSON gate report (-j)" },
430
+ ],
431
+ },
432
+ {
433
+ id: "probe",
434
+ path: ["probe"],
435
+ title: "probe",
436
+ description: "Run test flakiness stability probe across N repetitions",
437
+ category: "Inspect",
438
+ mutates: false,
439
+ risk: "low",
440
+ interactive: "never",
441
+ requiresRepository: true,
442
+ shortcuts: ["stability"],
443
+ examples: [
444
+ "agentctl probe",
445
+ "agentctl probe --repeat 10",
446
+ 'agentctl probe --repeat 5 --cmd "pytest"',
447
+ ],
448
+ flags: [
449
+ { name: "repeat", type: "string", description: "Number of probe executions (default: 5)" },
450
+ { name: "cmd", type: "string", description: "Test command to probe" },
451
+ { name: "test-cmd", type: "string", description: "Alias for cmd" },
452
+ { name: "verify-cmd", type: "string", description: "Alias for cmd" },
453
+ { name: "dry-run", type: "boolean", description: "Preview probe plan without execution (-d)" },
454
+ { name: "json", type: "boolean", description: "Output structured JSON probe telemetry (-j)" },
455
+ ],
456
+ },
457
+ {
458
+ id: "perf",
459
+ path: ["perf"],
460
+ title: "perf",
461
+ description: "Monitor Node.js event loop delay and Big-O performance lag",
462
+ category: "Inspect",
463
+ mutates: false,
464
+ risk: "low",
465
+ interactive: "never",
466
+ requiresRepository: true,
467
+ shortcuts: ["event-loop"],
468
+ examples: [
469
+ "agentctl perf",
470
+ 'agentctl perf --max-ms 50 --cmd "npm test"',
471
+ ],
472
+ flags: [
473
+ { name: "max-ms", type: "string", description: "Maximum allowable event loop delay threshold in ms" },
474
+ { name: "cmd", type: "string", description: "Command to execute during performance monitoring" },
475
+ { name: "test-cmd", type: "string", description: "Alias for cmd" },
476
+ { name: "verify-cmd", type: "string", description: "Alias for cmd" },
477
+ { name: "dry-run", type: "boolean", description: "Preview performance monitoring configuration (-d)" },
478
+ { name: "json", type: "boolean", description: "Output structured JSON performance report (-j)" },
479
+ ],
480
+ },
481
+ {
482
+ id: "dispatch",
483
+ path: ["dispatch"],
484
+ title: "dispatch",
485
+ description: "Dispatch a single task to an AI agent",
486
+ category: "Operate",
487
+ mutates: true,
488
+ risk: "moderate",
489
+ interactive: "never",
490
+ requiresRepository: true,
491
+ shortcuts: ["create"],
492
+ examples: [
493
+ 'agentctl dispatch --prompt "Add retry handling to src/webhook.js"',
494
+ 'agentctl dispatch -p "Fix type errors" --role bolt --tier fast',
495
+ 'agentctl dispatch --prompt-file task.md --dry-run',
496
+ ],
497
+ flags: [
498
+ { name: "prompt", type: "string", description: "Task prompt instructions (-p)" },
499
+ { name: "prompt-file", type: "string", description: "Read prompt from file (-f)" },
500
+ { name: "role", type: "string", description: "Specialist role (overseer, bolt, sentinel, janitor, a11y, scribe, spectator, alchemist) (-r)" },
501
+ { name: "tier", type: "string", description: "Execution tier override (fast | complex)" },
502
+ { name: "check-premise", type: "boolean", description: "Verify premise locally before dispatching" },
503
+ { name: "source", type: "string", description: "Jules repository source identifier (-s)" },
504
+ { name: "branch", type: "string", description: "Starting branch for task execution (-b)" },
505
+ { name: "repoless", type: "boolean", description: "Dispatch task in repoless execution mode" },
506
+ { name: "auto-pr", type: "boolean", description: "Automatically create PR upon completion" },
507
+ { name: "require-plan-approval", type: "boolean", description: "Require human approval for proposed plan" },
508
+ { name: "dry-run", type: "boolean", description: "Simulate dispatch without sending to provider (-d)" },
509
+ { name: "json", type: "boolean", description: "Output JSON structured dispatch result (-j)" },
510
+ ],
511
+ },
512
+ {
513
+ id: "bootstrap",
514
+ path: ["bootstrap"],
515
+ title: "bootstrap",
516
+ description: "Bootstrap zero-test repository with verification oracle",
517
+ category: "Configure",
518
+ mutates: true,
519
+ risk: "moderate",
520
+ interactive: "never",
521
+ requiresRepository: true,
522
+ shortcuts: ["bs"],
523
+ examples: [
524
+ "agentctl bootstrap",
525
+ "agentctl bootstrap --force",
526
+ ],
527
+ flags: [
528
+ { name: "force", type: "boolean", description: "Overwrite existing verification oracle or config (-f)" },
529
+ { name: "dry-run", type: "boolean", description: "Simulate bootstrap without writing files (-d)" },
530
+ { name: "json", type: "boolean", description: "Output JSON structured bootstrap result (-j)" },
531
+ ],
532
+ },
336
533
  ];
337
534
 
338
535
  /**
@@ -1,6 +1,7 @@
1
1
  import { existsSync, readdirSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { spawnSync } from "node:child_process";
4
+ import { isTaskFile } from "../engine.mjs";
4
5
 
5
6
  /**
6
7
  * Work out the one thing the operator should do next.
@@ -66,7 +67,7 @@ export function resolveNextStep(root, env = process.env) {
66
67
  const fallbackQueueDir = join(root, ".agent", "queue");
67
68
  const queueDir = existsSync(primaryQueueDir) ? primaryQueueDir : fallbackQueueDir;
68
69
  const queued = existsSync(queueDir)
69
- ? readdirSync(queueDir).filter((f) => f.endsWith(".md") || f.endsWith(".json") || f.endsWith(".yml")).length
70
+ ? readdirSync(queueDir).filter((f) => isTaskFile(f, queueDir)).length
70
71
  : 0;
71
72
  if (queued > 0) {
72
73
  return {
package/src/provider.mjs CHANGED
@@ -691,9 +691,9 @@ export function createProvider(spec = "jules", config = {}) {
691
691
  }
692
692
 
693
693
  if (providerSpec.type === "http") {
694
- const getSessionUrlTemplate = providerSpec.getSessionUrl || `${providerSpec.url}/${sessionId}`;
694
+ const getSessionUrlTemplate = ctx.customUrl || providerSpec.getSessionUrl || `${providerSpec.url}/${sessionId}`;
695
695
  const urlData = { sessionId, ...ctx };
696
- const url = interpolateString(getSessionUrlTemplate, urlData);
696
+ const url = ctx.customUrl || interpolateString(getSessionUrlTemplate, urlData);
697
697
 
698
698
  const headerData = { ...urlData, token: rawToken };
699
699
  const headers = {};
@@ -720,8 +720,9 @@ export function createProvider(spec = "jules", config = {}) {
720
720
  let res;
721
721
  try {
722
722
  res = await fetch(url, {
723
- method: "GET",
723
+ method: ctx.method || "GET",
724
724
  headers,
725
+ body: ctx.body ? JSON.stringify(ctx.body) : undefined,
725
726
  signal: AbortSignal.timeout(timeoutMs),
726
727
  });
727
728
  } catch (err) {
@@ -816,9 +817,9 @@ export function createProvider(spec = "jules", config = {}) {
816
817
  }
817
818
 
818
819
  if (providerSpec.type === "http") {
819
- const approvePlanUrlTemplate = providerSpec.approvePlanUrl || `${providerSpec.url}/${sessionId}:approvePlan`;
820
+ const approvePlanUrlTemplate = ctx.customUrl || providerSpec.approvePlanUrl || `${providerSpec.url}/${sessionId}:approvePlan`;
820
821
  const urlData = { sessionId, ...ctx };
821
- const url = interpolateString(approvePlanUrlTemplate, urlData);
822
+ const url = ctx.customUrl || interpolateString(approvePlanUrlTemplate, urlData);
822
823
 
823
824
  const headerData = { ...urlData, token: rawToken };
824
825
  const headers = {};
@@ -918,6 +919,94 @@ export function createProvider(spec = "jules", config = {}) {
918
919
 
919
920
  throw new Error(`Unsupported provider type: ${providerSpec.type}`);
920
921
  },
922
+
923
+ async listSessions(ctx = {}) {
924
+ if (!ctx || typeof ctx !== "object") ctx = {};
925
+ if (ctx.dryRun) return { sessions: [], raw: {} };
926
+ if (providerSpec.type === "http") {
927
+ const baseUrl = providerSpec.url || "https://jules.googleapis.com/v1alpha/sessions";
928
+ const params = new URLSearchParams();
929
+ if (ctx.pageSize) params.set("pageSize", String(ctx.pageSize));
930
+ if (ctx.pageToken) params.set("pageToken", String(ctx.pageToken));
931
+ const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
932
+ const res = await this.getSession("", { ...ctx, customUrl: url });
933
+ return {
934
+ sessions: res?.raw?.sessions || [],
935
+ nextPageToken: res?.raw?.nextPageToken,
936
+ raw: res?.raw || {},
937
+ };
938
+ }
939
+ return { sessions: [], raw: {} };
940
+ },
941
+
942
+ async listActivities(sessionId, ctx = {}) {
943
+ if (!sessionId || typeof sessionId !== "string") {
944
+ throw new TypeError("listActivities() requires a valid sessionId string");
945
+ }
946
+ if (!ctx || typeof ctx !== "object") ctx = {};
947
+ if (ctx.dryRun) return { activities: [], raw: {} };
948
+ if (providerSpec.type === "http") {
949
+ const baseUrl = `${providerSpec.url || "https://jules.googleapis.com/v1alpha/sessions"}/${sessionId}/activities`;
950
+ const params = new URLSearchParams();
951
+ if (ctx.pageSize) params.set("pageSize", String(ctx.pageSize));
952
+ if (ctx.pageToken) params.set("pageToken", String(ctx.pageToken));
953
+ const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
954
+ const res = await this.getSession("", { ...ctx, customUrl: url });
955
+ return {
956
+ activities: res?.raw?.activities || [],
957
+ nextPageToken: res?.raw?.nextPageToken,
958
+ raw: res?.raw || {},
959
+ };
960
+ }
961
+ return { activities: [], raw: {} };
962
+ },
963
+
964
+ async archiveSession(sessionId, ctx = {}) {
965
+ if (!sessionId || typeof sessionId !== "string") {
966
+ throw new TypeError("archiveSession() requires a valid sessionId string");
967
+ }
968
+ if (!ctx || typeof ctx !== "object") ctx = {};
969
+ if (ctx.dryRun) return { id: sessionId, archived: true, raw: {} };
970
+ if (providerSpec.type === "http") {
971
+ const url = `${providerSpec.url || "https://jules.googleapis.com/v1alpha/sessions"}/${sessionId}:archive`;
972
+ const res = await this.approvePlan(sessionId, { ...ctx, customUrl: url });
973
+ return { id: sessionId, archived: true, raw: res?.raw || {} };
974
+ }
975
+ return { id: sessionId, archived: true, raw: {} };
976
+ },
977
+
978
+ async deleteSession(sessionId, ctx = {}) {
979
+ if (!sessionId || typeof sessionId !== "string") {
980
+ throw new TypeError("deleteSession() requires a valid sessionId string");
981
+ }
982
+ if (!ctx || typeof ctx !== "object") ctx = {};
983
+ if (ctx.dryRun) return { id: sessionId, deleted: true, raw: {} };
984
+ if (providerSpec.type === "http") {
985
+ const url = `${providerSpec.url || "https://jules.googleapis.com/v1alpha/sessions"}/${sessionId}`;
986
+ const res = await this.getSession("", { ...ctx, customUrl: url, method: "DELETE" });
987
+ return { id: sessionId, deleted: true, raw: res?.raw || {} };
988
+ }
989
+ return { id: sessionId, deleted: true, raw: {} };
990
+ },
991
+
992
+ async listSources(ctx = {}) {
993
+ if (!ctx || typeof ctx !== "object") ctx = {};
994
+ if (ctx.dryRun) return { sources: [], raw: {} };
995
+ if (providerSpec.type === "http") {
996
+ const baseUrl = "https://jules.googleapis.com/v1alpha/sources";
997
+ const params = new URLSearchParams();
998
+ if (ctx.pageSize) params.set("pageSize", String(ctx.pageSize));
999
+ if (ctx.pageToken) params.set("pageToken", String(ctx.pageToken));
1000
+ const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
1001
+ const res = await this.getSession("", { ...ctx, customUrl: url });
1002
+ return {
1003
+ sources: res?.raw?.sources || [],
1004
+ nextPageToken: res?.raw?.nextPageToken,
1005
+ raw: res?.raw || {},
1006
+ };
1007
+ }
1008
+ return { sources: [], raw: {} };
1009
+ },
921
1010
  };
922
1011
  }
923
1012
 
@@ -1038,6 +1127,26 @@ export function createFailoverProvider(providers = ["jules"], config = {}) {
1038
1127
  }
1039
1128
  },
1040
1129
 
1130
+ async listSessions(ctx = {}) {
1131
+ return providerList[0].listSessions(ctx);
1132
+ },
1133
+
1134
+ async listActivities(sessionId, ctx = {}) {
1135
+ return providerList[0].listActivities(sessionId, ctx);
1136
+ },
1137
+
1138
+ async archiveSession(sessionId, ctx = {}) {
1139
+ return providerList[0].archiveSession(sessionId, ctx);
1140
+ },
1141
+
1142
+ async deleteSession(sessionId, ctx = {}) {
1143
+ return providerList[0].deleteSession(sessionId, ctx);
1144
+ },
1145
+
1146
+ async listSources(ctx = {}) {
1147
+ return providerList[0].listSources(ctx);
1148
+ },
1149
+
1041
1150
  validate() {
1042
1151
  return providerList.every((p) => typeof p.validate !== "function" || p.validate());
1043
1152
  },
@@ -1108,5 +1217,25 @@ export function createSyntaxVerifiedProvider(fastProvider, complexProvider, conf
1108
1217
  approvePlan(...args) {
1109
1218
  return fastProvider.approvePlan(...args);
1110
1219
  },
1220
+
1221
+ listSessions(...args) {
1222
+ return typeof fastProvider.listSessions === "function" ? fastProvider.listSessions(...args) : { sessions: [] };
1223
+ },
1224
+
1225
+ listActivities(...args) {
1226
+ return typeof fastProvider.listActivities === "function" ? fastProvider.listActivities(...args) : { activities: [] };
1227
+ },
1228
+
1229
+ archiveSession(...args) {
1230
+ return typeof fastProvider.archiveSession === "function" ? fastProvider.archiveSession(...args) : { id: args[0], archived: true };
1231
+ },
1232
+
1233
+ deleteSession(...args) {
1234
+ return typeof fastProvider.deleteSession === "function" ? fastProvider.deleteSession(...args) : { id: args[0], deleted: true };
1235
+ },
1236
+
1237
+ listSources(...args) {
1238
+ return typeof fastProvider.listSources === "function" ? fastProvider.listSources(...args) : { sources: [] };
1239
+ },
1111
1240
  };
1112
1241
  }