@benzotti/jedi 0.1.15 → 0.1.18

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.
@@ -88,17 +88,28 @@ jobs:
88
88
  grep -qxF "$pattern" .git/info/exclude 2>/dev/null || echo "$pattern" >> .git/info/exclude
89
89
  done
90
90
 
91
- # Run Jedi via the official Claude Code Action (tag mode posts comments automatically)
92
- # NOTE: No 'prompt' input — Jedi instructions live in .claude/CLAUDE.md (written by bootstrap)
93
- # Using prompt would switch to agent mode which doesn't post comments back to the PR/issue
91
+ # Install Claude Code CLI (required by Jedi for AI invocations)
92
+ - name: Install Claude Code
93
+ run: bun install -g @anthropic-ai/claude-code
94
+
95
+ # Run Jedi CLI directly — full pipeline with routing, agents, and comment posting
94
96
  - name: Run Jedi
95
- uses: anthropics/claude-code-action@v1
96
- with:
97
- anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
98
- trigger_phrase: 'Hey Jedi'
99
- bot_name: 'jedi[bot]'
97
+ run: |
98
+ COMMENT_BODY="${{ github.event.comment.body }}"
99
+ COMMENT_ID="${{ github.event.comment.id }}"
100
+ PR_NUMBER="${{ github.event.issue.pull_request && github.event.issue.number || '' }}"
101
+ ISSUE_NUMBER="${{ github.event.issue.number }}"
102
+
103
+ ARGS="--repo ${{ github.repository }}"
104
+ [ -n "$COMMENT_ID" ] && ARGS="$ARGS --comment-id $COMMENT_ID"
105
+ [ -n "$PR_NUMBER" ] && ARGS="$ARGS --pr-number $PR_NUMBER"
106
+ [ -n "$ISSUE_NUMBER" ] && ARGS="$ARGS --issue-number $ISSUE_NUMBER"
107
+
108
+ bunx @benzotti/jedi@latest action "$COMMENT_BODY" $ARGS
100
109
  env:
110
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
101
111
  CLICKUP_API_TOKEN: ${{ secrets.CLICKUP_API_TOKEN }}
112
+ GH_TOKEN: ${{ github.token }}
102
113
 
103
114
  # Save Jedi state — framework, config, persistence all cached together
104
115
  - name: Save Jedi state
package/dist/index.js CHANGED
@@ -9604,6 +9604,7 @@ async function spawnClaude(prompt2, opts) {
9604
9604
  const reader = proc.stdout.getReader();
9605
9605
  const decoder = new TextDecoder;
9606
9606
  let buffer = "";
9607
+ let lastTextResponse = "";
9607
9608
  try {
9608
9609
  while (true) {
9609
9610
  const { done, value } = await reader.read();
@@ -9622,6 +9623,16 @@ async function spawnClaude(prompt2, opts) {
9622
9623
  const output = formatStreamEvent(event);
9623
9624
  if (output)
9624
9625
  process.stdout.write(output);
9626
+ if (event.type === "assistant" && event.message?.content) {
9627
+ for (const block of event.message.content) {
9628
+ if (block.type === "text" && block.text) {
9629
+ lastTextResponse = block.text;
9630
+ }
9631
+ }
9632
+ }
9633
+ if (event.type === "result" && event.result) {
9634
+ lastTextResponse = event.result;
9635
+ }
9625
9636
  } catch {}
9626
9637
  }
9627
9638
  }
@@ -9631,13 +9642,23 @@ async function spawnClaude(prompt2, opts) {
9631
9642
  const output = formatStreamEvent(event);
9632
9643
  if (output)
9633
9644
  process.stdout.write(output);
9645
+ if (event.type === "assistant" && event.message?.content) {
9646
+ for (const block of event.message.content) {
9647
+ if (block.type === "text" && block.text) {
9648
+ lastTextResponse = block.text;
9649
+ }
9650
+ }
9651
+ }
9652
+ if (event.type === "result" && event.result) {
9653
+ lastTextResponse = event.result;
9654
+ }
9634
9655
  } catch {}
9635
9656
  }
9636
9657
  } catch {}
9637
9658
  const exitCode = await proc.exited;
9638
9659
  process.stdout.write(`
9639
9660
  `);
9640
- return { exitCode };
9661
+ return { exitCode, response: lastTextResponse };
9641
9662
  }
9642
9663
 
9643
9664
  // src/storage/index.ts
@@ -11045,11 +11066,28 @@ function formatTicketAsContext(ticket) {
11045
11066
 
11046
11067
  // src/utils/github.ts
11047
11068
  async function postGitHubComment(repo, issueNumber, body) {
11048
- await exec([
11069
+ const { stdout: stdout2, exitCode } = await exec([
11049
11070
  "gh",
11050
11071
  "api",
11051
11072
  `repos/${repo}/issues/${issueNumber}/comments`,
11052
11073
  "-f",
11074
+ `body=${body}`,
11075
+ "--jq",
11076
+ ".id"
11077
+ ]);
11078
+ if (exitCode === 0 && stdout2.trim()) {
11079
+ return Number(stdout2.trim());
11080
+ }
11081
+ return null;
11082
+ }
11083
+ async function updateGitHubComment(repo, commentId, body) {
11084
+ await exec([
11085
+ "gh",
11086
+ "api",
11087
+ "-X",
11088
+ "PATCH",
11089
+ `repos/${repo}/issues/comments/${commentId}`,
11090
+ "-f",
11053
11091
  `body=${body}`
11054
11092
  ]);
11055
11093
  }
@@ -11085,7 +11123,7 @@ async function fetchCommentThread(repo, issueNumber) {
11085
11123
  author: parsed.author,
11086
11124
  body: parsed.body,
11087
11125
  createdAt: parsed.createdAt,
11088
- isJedi: parsed.body.includes("Powered by [@benzotti/jedi]") || parsed.body.includes("Jedi plan") || parsed.body.includes("Jedi quick") || parsed.body.includes("Jedi implement")
11126
+ isJedi: parsed.body.includes("### \u2694\uFE0F Jedi")
11089
11127
  });
11090
11128
  } catch {}
11091
11129
  }
@@ -11126,21 +11164,19 @@ function buildConversationContext(thread, currentCommentId) {
11126
11164
  return { history: lines.join(`
11127
11165
  `), previousJediRuns, isFollowUp };
11128
11166
  }
11129
- function formatResultComment(command, success, summary) {
11130
- const status = success ? "Completed" : "Failed";
11131
- const icon = success ? "white_check_mark" : "x";
11167
+ function formatJediComment(response) {
11132
11168
  return [
11133
- `### :${icon}: Jedi ${command} \u2014 ${status}`,
11134
- ``,
11135
- `<details>`,
11136
- `<summary>Details</summary>`,
11137
- ``,
11138
- summary,
11169
+ `### \u2694\uFE0F Jedi`,
11139
11170
  ``,
11140
- `</details>`,
11171
+ response
11172
+ ].join(`
11173
+ `);
11174
+ }
11175
+ function formatErrorComment(command, summary) {
11176
+ return [
11177
+ `### \u2694\uFE0F Jedi`,
11141
11178
  ``,
11142
- `---`,
11143
- `_Powered by [@benzotti/jedi](https://github.com/zottiben/jedi)_`
11179
+ `**${command} failed.** ${summary}`
11144
11180
  ].join(`
11145
11181
  `);
11146
11182
  }
@@ -11262,6 +11298,11 @@ var actionCommand = defineCommand({
11262
11298
  if (repo && commentId) {
11263
11299
  await reactToComment(repo, commentId, "eyes").catch(() => {});
11264
11300
  }
11301
+ let placeholderCommentId = null;
11302
+ if (repo && issueNumber) {
11303
+ const thinkingBody = formatJediComment("_Thinking..._");
11304
+ placeholderCommentId = await postGitHubComment(repo, issueNumber, thinkingBody).catch(() => null);
11305
+ }
11265
11306
  if (intent.command === "ping") {
11266
11307
  const { existsSync: existsSync13 } = await import("fs");
11267
11308
  const { join: join12 } = await import("path");
@@ -11277,8 +11318,8 @@ var actionCommand = defineCommand({
11277
11318
  version = pkg.version;
11278
11319
  }
11279
11320
  } catch {}
11280
- const lines = [
11281
- `### Jedi Framework Status`,
11321
+ const statusBody = [
11322
+ `**Framework Status**`,
11282
11323
  ``,
11283
11324
  `| Component | Status |`,
11284
11325
  `|-----------|--------|`,
@@ -11286,19 +11327,20 @@ var actionCommand = defineCommand({
11286
11327
  `| CLAUDE.md | ${claudeMdExists ? "found" : "missing"} |`,
11287
11328
  `| State config | ${stateExists ? "found" : "missing"} |`,
11288
11329
  `| Learnings | ${learningsExists ? "found" : "missing"} |`,
11289
- `| Version | \`${version}\` |`,
11290
- ``,
11291
- `---`,
11292
- `_Powered by [@benzotti/jedi](https://github.com/zottiben/jedi)_`
11293
- ];
11294
- if (repo && issueNumber) {
11295
- await postGitHubComment(repo, issueNumber, lines.join(`
11296
- `)).catch((err) => {
11330
+ `| Version | \`${version}\` |`
11331
+ ].join(`
11332
+ `);
11333
+ const finalBody = formatJediComment(statusBody);
11334
+ if (repo && placeholderCommentId) {
11335
+ await updateGitHubComment(repo, placeholderCommentId, finalBody).catch((err) => {
11336
+ consola.error("Failed to update ping comment:", err);
11337
+ });
11338
+ } else if (repo && issueNumber) {
11339
+ await postGitHubComment(repo, issueNumber, finalBody).catch((err) => {
11297
11340
  consola.error("Failed to post ping comment:", err);
11298
11341
  });
11299
11342
  } else {
11300
- console.log(lines.join(`
11301
- `));
11343
+ console.log(finalBody);
11302
11344
  }
11303
11345
  if (repo && commentId) {
11304
11346
  await reactToComment(repo, commentId, "+1").catch(() => {});
@@ -11355,9 +11397,13 @@ var actionCommand = defineCommand({
11355
11397
  `## Instructions`,
11356
11398
  `Review the previous conversation above. The user is iterating on work Jedi already started.`,
11357
11399
  ``,
11400
+ `IMPORTANT: Always be conversational. If the user asks a question, ANSWER IT FIRST before taking any action.`,
11401
+ `Explain your reasoning, then describe what you'll do (if anything), then do it.`,
11402
+ `Never silently make changes without explaining why.`,
11403
+ ``,
11404
+ `- If the feedback is a **question** ("why did you...", "what about...", "can you explain..."), answer it conversationally first. If the answer implies a change is needed, explain that and then apply it.`,
11358
11405
  `- If the feedback is an **approval** ("approved", "lgtm", "looks good", "ship it"), finalise the current work \u2014 create commits and/or a PR as appropriate.`,
11359
- `- If the feedback is a **refinement** ("change task 2", "use a different approach", "add error handling"), apply the requested changes to the existing plan or implementation. Present an updated summary when done.`,
11360
- `- If the feedback is a **question**, answer it with full context from the conversation.`,
11406
+ `- If the feedback is a **refinement** ("change task 2", "use a different approach", "add error handling"), explain what you're changing and why, then apply the changes. Present an updated summary when done.`,
11361
11407
  ``,
11362
11408
  `Read state.yaml and any existing plan files to understand what was previously done. Apply changes incrementally \u2014 do not restart from scratch.`
11363
11409
  ].join(`
@@ -11382,7 +11428,16 @@ The above is prior conversation on this issue for context.
11382
11428
  ticketContext ? `
11383
11429
  Use the ClickUp ticket above as the primary requirements source.` : ``,
11384
11430
  ``,
11385
- `Follow the planning workflow in your spec. Present the plan summary when complete and ask for feedback. The user will respond via another GitHub comment.`
11431
+ `Follow the planning workflow in your spec. When presenting the plan:`,
11432
+ `1. Start with a brief summary of the approach`,
11433
+ `2. Include the FULL plan in a collapsible details block using this format:`,
11434
+ ` <details>`,
11435
+ ` <summary>View full plan</summary>`,
11436
+ ` `,
11437
+ ` [full plan content here as markdown]`,
11438
+ ` `,
11439
+ ` </details>`,
11440
+ `3. Ask for feedback. The user will respond via another GitHub comment.`
11386
11441
  ].join(`
11387
11442
  `);
11388
11443
  break;
@@ -11447,11 +11502,13 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11447
11502
  }
11448
11503
  }
11449
11504
  let success = true;
11505
+ let fullResponse = "";
11450
11506
  try {
11451
- const { exitCode } = await spawnClaude(prompt2, {
11507
+ const { exitCode, response } = await spawnClaude(prompt2, {
11452
11508
  cwd,
11453
11509
  permissionMode: "bypassPermissions"
11454
11510
  });
11511
+ fullResponse = response;
11455
11512
  if (exitCode !== 0) {
11456
11513
  success = false;
11457
11514
  consola.error(`Claude exited with code ${exitCode}`);
@@ -11477,6 +11534,13 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11477
11534
  if (implResult.exitCode !== 0) {
11478
11535
  success = false;
11479
11536
  }
11537
+ if (implResult.response) {
11538
+ fullResponse += `
11539
+
11540
+ ---
11541
+
11542
+ ` + implResult.response;
11543
+ }
11480
11544
  }
11481
11545
  } catch (err) {
11482
11546
  success = false;
@@ -11489,11 +11553,23 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11489
11553
  consola.info("Codebase index persisted to storage");
11490
11554
  if (repo && issueNumber) {
11491
11555
  const actionLabel = intent.isFeedback ? "feedback" : intent.command;
11492
- const summary = success ? `Executed \`${actionLabel}\` successfully.${saved.learningsSaved ? " Learnings updated." : ""}` : `Execution of \`${actionLabel}\` failed. Check workflow logs for details.`;
11493
- const commentBody = formatResultComment(actionLabel, success, summary);
11494
- await postGitHubComment(repo, issueNumber, commentBody).catch((err) => {
11495
- consola.error("Failed to post result comment:", err);
11496
- });
11556
+ let commentBody;
11557
+ if (success && fullResponse) {
11558
+ commentBody = formatJediComment(fullResponse);
11559
+ } else if (!success) {
11560
+ commentBody = formatErrorComment(actionLabel, "Check workflow logs for details.");
11561
+ } else {
11562
+ commentBody = formatJediComment(`Executed \`${actionLabel}\` successfully.`);
11563
+ }
11564
+ if (placeholderCommentId) {
11565
+ await updateGitHubComment(repo, placeholderCommentId, commentBody).catch((err) => {
11566
+ consola.error("Failed to update result comment:", err);
11567
+ });
11568
+ } else {
11569
+ await postGitHubComment(repo, issueNumber, commentBody).catch((err) => {
11570
+ consola.error("Failed to post result comment:", err);
11571
+ });
11572
+ }
11497
11573
  }
11498
11574
  if (repo && commentId) {
11499
11575
  const reaction = success ? "+1" : "-1";
@@ -11565,7 +11641,7 @@ var setupActionCommand = defineCommand({
11565
11641
  // package.json
11566
11642
  var package_default = {
11567
11643
  name: "@benzotti/jedi",
11568
- version: "0.1.15",
11644
+ version: "0.1.18",
11569
11645
  description: "JDI - Context-efficient AI development framework for Claude Code",
11570
11646
  type: "module",
11571
11647
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benzotti/jedi",
3
- "version": "0.1.15",
3
+ "version": "0.1.18",
4
4
  "description": "JDI - Context-efficient AI development framework for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {