@chernabog/sdk 0.2.0 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chernabog/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "license": "MIT",
5
5
  "description": "Services and helpers for writing Chernabog flows and steps",
6
6
  "repository": {
package/src/implement.ts CHANGED
@@ -483,20 +483,27 @@ export const workflow = (item: WorkItem) =>
483
483
  Effect.gen(function* () {
484
484
  const issue = yield* issueOf(item);
485
485
  const { branch } = yield* claim(issue);
486
- const worktree = yield* prepareWorktree(branch);
487
- const outcome = yield* implementWithAgent(issue, worktree);
488
-
489
- if (outcome.status === 'needs-clarification') return yield* askForClarification(issue, outcome).pipe(Effect.flatMap(endForPerson));
490
-
491
486
  let pullRequest = Option.none<number>();
487
+ const toPerson = (reason: string) => handToHuman(issue, reason, pullRequest).pipe(Effect.flatMap(endForPerson));
492
488
 
493
489
  return yield* Effect.gen(function* () {
494
- yield* localGate(worktree);
495
- yield* push('push', worktree, branch);
496
- const opened = yield* openPullRequest(issue, outcome);
497
- pullRequest = Option.some(opened.number);
498
- yield* waitForCi(opened.number, worktree, { ...thisRunsSession, branch });
499
-
500
- return yield* handOff(issue, opened, outcome);
501
- }).pipe(Effect.catchTag('NeedsHuman', (needsHuman) => handToHuman(issue, needsHuman.reason, pullRequest).pipe(Effect.flatMap(endForPerson))));
490
+ const worktree = yield* prepareWorktree(branch);
491
+ const outcome = yield* implementWithAgent(issue, worktree);
492
+
493
+ if (outcome.status === 'needs-clarification') return yield* askForClarification(issue, outcome).pipe(Effect.flatMap(endForPerson));
494
+
495
+ return yield* Effect.gen(function* () {
496
+ yield* localGate(worktree);
497
+ yield* push('push', worktree, branch);
498
+ const opened = yield* openPullRequest(issue, outcome);
499
+ pullRequest = Option.some(opened.number);
500
+ yield* waitForCi(opened.number, worktree, { ...thisRunsSession, branch });
501
+
502
+ return yield* handOff(issue, opened, outcome);
503
+ }).pipe(Effect.catchTag('NeedsHuman', (needsHuman) => toPerson(needsHuman.reason)));
504
+ }).pipe(
505
+ // Any other failure once the issue is claimed hands it to a person, rather
506
+ // than leaving it claimed with nobody working on it.
507
+ Effect.catchTag('StepFailed', (failed) => toPerson(`${failed.step}: ${failed.message}`)),
508
+ );
502
509
  });
package/src/services.ts CHANGED
@@ -38,7 +38,20 @@ export const Board = Schema.Struct({ projectNumber: Schema.Finite, readyStatus:
38
38
  export type Board = typeof Board.Type;
39
39
 
40
40
  // configDir none is the agent's default home (~/.claude, ~/.codex).
41
- export const Account = Schema.Struct({ name: Schema.String, configDir: Schema.Option(Schema.String), expectedEmail: Schema.Option(Schema.String) });
41
+ // oauthTokenEnv names the environment variable holding a Claude login token
42
+ // (from `claude setup-token`), for a host with no login of its own, such as CI.
43
+ // usageGate none launches without reading usage, which such a token cannot.
44
+ export const UsageGateMode = Schema.Literals(['usage', 'none']);
45
+
46
+ export type UsageGateMode = typeof UsageGateMode.Type;
47
+
48
+ export const Account = Schema.Struct({
49
+ name: Schema.String,
50
+ configDir: Schema.Option(Schema.String),
51
+ expectedEmail: Schema.Option(Schema.String),
52
+ oauthTokenEnv: Schema.Option(Schema.String),
53
+ usageGate: UsageGateMode,
54
+ });
42
55
 
43
56
  export type Account = typeof Account.Type;
44
57