@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.
- package/action/workflow-template.yml +19 -8
- package/dist/index.js +113 -37
- package/package.json +1 -1
|
@@ -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
|
-
#
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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("
|
|
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
|
|
11130
|
-
const status = success ? "Completed" : "Failed";
|
|
11131
|
-
const icon = success ? "white_check_mark" : "x";
|
|
11167
|
+
function formatJediComment(response) {
|
|
11132
11168
|
return [
|
|
11133
|
-
`###
|
|
11134
|
-
``,
|
|
11135
|
-
`<details>`,
|
|
11136
|
-
`<summary>Details</summary>`,
|
|
11137
|
-
``,
|
|
11138
|
-
summary,
|
|
11169
|
+
`### \u2694\uFE0F Jedi`,
|
|
11139
11170
|
``,
|
|
11140
|
-
|
|
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
|
|
11281
|
-
|
|
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
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
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(
|
|
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"),
|
|
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.
|
|
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
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
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.
|
|
11644
|
+
version: "0.1.18",
|
|
11569
11645
|
description: "JDI - Context-efficient AI development framework for Claude Code",
|
|
11570
11646
|
type: "module",
|
|
11571
11647
|
bin: {
|