@jive-ai/cli 0.0.47 → 0.0.48
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/dist/index.mjs +115 -18
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -774,6 +774,7 @@ const queries = {
|
|
|
774
774
|
gitBranch
|
|
775
775
|
previewUrl
|
|
776
776
|
autoApprove
|
|
777
|
+
linkedIssueNumber
|
|
777
778
|
project {
|
|
778
779
|
id
|
|
779
780
|
name
|
|
@@ -1072,6 +1073,22 @@ const mutations = {
|
|
|
1072
1073
|
}
|
|
1073
1074
|
}
|
|
1074
1075
|
}
|
|
1076
|
+
`),
|
|
1077
|
+
CommentCreate: graphql(`
|
|
1078
|
+
mutation CommentCreate($input: CreateCommentInput!) {
|
|
1079
|
+
commentCreate(input: $input) {
|
|
1080
|
+
success
|
|
1081
|
+
comment {
|
|
1082
|
+
id
|
|
1083
|
+
body
|
|
1084
|
+
htmlUrl
|
|
1085
|
+
}
|
|
1086
|
+
errors {
|
|
1087
|
+
message
|
|
1088
|
+
code
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1075
1092
|
`),
|
|
1076
1093
|
RegisterRunner: graphql(`
|
|
1077
1094
|
mutation RegisterRunner($input: RegisterRunnerInput!) {
|
|
@@ -1539,7 +1556,8 @@ var ApiClient = class {
|
|
|
1539
1556
|
description: data.task.description || "",
|
|
1540
1557
|
status: data.task.status.toLowerCase().replace("_", "-"),
|
|
1541
1558
|
gitBranch: data.task.gitBranch || "",
|
|
1542
|
-
previewUrl: data.task.previewUrl || void 0
|
|
1559
|
+
previewUrl: data.task.previewUrl || void 0,
|
|
1560
|
+
linkedIssueNumber: data.task.linkedIssueNumber ?? null
|
|
1543
1561
|
},
|
|
1544
1562
|
plan: data.task.currentPlan ? {
|
|
1545
1563
|
id: parseInt(data.task.currentPlan.id, 10),
|
|
@@ -1652,6 +1670,22 @@ var ApiClient = class {
|
|
|
1652
1670
|
}
|
|
1653
1671
|
};
|
|
1654
1672
|
}
|
|
1673
|
+
async createComment(projectId, data) {
|
|
1674
|
+
const result = await (await getGraphQLClient()).request(mutations.CommentCreate, { input: {
|
|
1675
|
+
projectId: String(projectId),
|
|
1676
|
+
issueNumber: data.issueNumber,
|
|
1677
|
+
content: data.content
|
|
1678
|
+
} });
|
|
1679
|
+
if (result.commentCreate.errors?.length) throw this.formatError({ message: result.commentCreate.errors[0].message });
|
|
1680
|
+
return {
|
|
1681
|
+
success: result.commentCreate.success,
|
|
1682
|
+
comment: {
|
|
1683
|
+
id: result.commentCreate.comment.id,
|
|
1684
|
+
body: result.commentCreate.comment.body,
|
|
1685
|
+
htmlUrl: result.commentCreate.comment.htmlUrl
|
|
1686
|
+
}
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1655
1689
|
async getTaskSteps(id) {
|
|
1656
1690
|
const data = await (await getGraphQLClient()).request(queries.GetPlan, { id: String(id) });
|
|
1657
1691
|
if (!data.plan?.steps) return [];
|
|
@@ -2050,7 +2084,7 @@ async function createGraphQLClient() {
|
|
|
2050
2084
|
|
|
2051
2085
|
//#endregion
|
|
2052
2086
|
//#region package.json
|
|
2053
|
-
var version = "0.0.
|
|
2087
|
+
var version = "0.0.48";
|
|
2054
2088
|
|
|
2055
2089
|
//#endregion
|
|
2056
2090
|
//#region src/runner/index.ts
|
|
@@ -2210,37 +2244,41 @@ var TaskRunner = class {
|
|
|
2210
2244
|
}
|
|
2211
2245
|
}
|
|
2212
2246
|
async fetchTaskProcess(taskId) {
|
|
2213
|
-
const
|
|
2214
|
-
|
|
2247
|
+
const key = taskId.toString();
|
|
2248
|
+
const existing = this.taskProcesses[key];
|
|
2249
|
+
if (existing) return existing;
|
|
2215
2250
|
if (Object.values(this.taskProcesses).filter((p) => p !== null).length >= this.maxConcurrentTasks) {
|
|
2216
2251
|
console.warn(chalk.yellow(`Maximum concurrent tasks reached (${this.maxConcurrentTasks})`));
|
|
2217
2252
|
return null;
|
|
2218
2253
|
}
|
|
2254
|
+
const initPromise = this.initTaskProcess(taskId);
|
|
2255
|
+
this.taskProcesses[key] = initPromise;
|
|
2256
|
+
const result = await initPromise;
|
|
2257
|
+
if (!result && this.taskProcesses[key] === initPromise) this.taskProcesses[key] = null;
|
|
2258
|
+
return result;
|
|
2259
|
+
}
|
|
2260
|
+
async initTaskProcess(taskId) {
|
|
2219
2261
|
const ctx = await this.fetchTaskContext(taskId);
|
|
2220
2262
|
if (!ctx) {
|
|
2221
2263
|
console.error(chalk.red(`Failed to fetch context for task ${taskId}`));
|
|
2222
2264
|
return null;
|
|
2223
2265
|
}
|
|
2224
|
-
return
|
|
2225
|
-
|
|
2266
|
+
return {
|
|
2267
|
+
process: this.config.type === "docker" ? await spawnTaskDocker(ctx, this.config, {
|
|
2226
2268
|
onMessage: (message) => this.onTaskMessage(ctx.taskId, message),
|
|
2227
2269
|
onError: () => {},
|
|
2228
2270
|
onClose: () => {
|
|
2229
2271
|
this.taskProcesses[ctx.taskId.toString()] = null;
|
|
2230
2272
|
}
|
|
2231
|
-
}) :
|
|
2273
|
+
}) : spawnTask(ctx, {
|
|
2232
2274
|
onMessage: (message) => this.onTaskMessage(ctx.taskId, message),
|
|
2233
2275
|
onError: () => {},
|
|
2234
2276
|
onClose: () => {
|
|
2235
2277
|
this.taskProcesses[ctx.taskId.toString()] = null;
|
|
2236
2278
|
}
|
|
2237
|
-
})
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
ctx
|
|
2241
|
-
});
|
|
2242
|
-
});
|
|
2243
|
-
});
|
|
2279
|
+
}),
|
|
2280
|
+
ctx
|
|
2281
|
+
};
|
|
2244
2282
|
}
|
|
2245
2283
|
async sendToTask(taskId, message) {
|
|
2246
2284
|
const result = await this.fetchTaskProcess(taskId);
|
|
@@ -2435,7 +2473,13 @@ var TaskRunner = class {
|
|
|
2435
2473
|
`);
|
|
2436
2474
|
const pendingTasks = (await client.request(query$1, { limit: availableSlots })).tasks.edges.map((e$2) => e$2.node);
|
|
2437
2475
|
if (pendingTasks.length > 0) console.log(chalk.yellow(`Found ${pendingTasks.length} pending task(s) to pick up`));
|
|
2438
|
-
for (const task of pendingTasks)
|
|
2476
|
+
for (const task of pendingTasks) {
|
|
2477
|
+
if (this.taskProcesses[task.id]) {
|
|
2478
|
+
console.log(chalk.dim(`Task ${task.id} already managed, skipping`));
|
|
2479
|
+
continue;
|
|
2480
|
+
}
|
|
2481
|
+
await this.pickupPendingTask(parseInt(task.id));
|
|
2482
|
+
}
|
|
2439
2483
|
} catch (error$1) {
|
|
2440
2484
|
if (!error$1.message?.includes("Unable to connect")) console.error(chalk.red(`Failed to poll for pending tasks: ${error$1.message}`));
|
|
2441
2485
|
}
|
|
@@ -2736,8 +2780,13 @@ function createTasksSdkServer(task) {
|
|
|
2736
2780
|
|
|
2737
2781
|
If the next step contains a subagent, you must invoke the subagent for the next step.
|
|
2738
2782
|
|
|
2739
|
-
If result contains \`isComplete: true\`, then the task is complete and you MUST
|
|
2740
|
-
The
|
|
2783
|
+
If result contains \`isComplete: true\`, then the task is complete and you MUST add an issue comment using the \`add_issue_comment\` tool.
|
|
2784
|
+
The comment MUST include:
|
|
2785
|
+
- A very concise (1-2 sentence) description of the changes
|
|
2786
|
+
- A reference to the branch: ${task.branch}
|
|
2787
|
+
- A link to the task: https://getjive.app/app/tasks/${task.id}
|
|
2788
|
+
|
|
2789
|
+
The user is expecting issue comments to be automatically created when the task is complete.
|
|
2741
2790
|
`, {
|
|
2742
2791
|
stepId: z.number(),
|
|
2743
2792
|
commitMessage: z.string().describe("Concise commit message describing changes"),
|
|
@@ -2801,6 +2850,51 @@ function createTasksSdkServer(task) {
|
|
|
2801
2850
|
};
|
|
2802
2851
|
}
|
|
2803
2852
|
}),
|
|
2853
|
+
tool("add_issue_comment", "Add a comment to the linked issue on GitHub or GitLab. Use this to post updates, summaries, or task completion notices on the issue.", { content: z.string().describe("The comment body to post on the issue (supports markdown)") }, async (args) => {
|
|
2854
|
+
if (!context) return {
|
|
2855
|
+
content: [{
|
|
2856
|
+
type: "text",
|
|
2857
|
+
text: "Error: Task context not initialized"
|
|
2858
|
+
}],
|
|
2859
|
+
isError: true
|
|
2860
|
+
};
|
|
2861
|
+
try {
|
|
2862
|
+
const apiClient$1 = getApiClient();
|
|
2863
|
+
const { task: taskData, project } = await apiClient$1.getTask(context.taskId);
|
|
2864
|
+
if (!project) return {
|
|
2865
|
+
content: [{
|
|
2866
|
+
type: "text",
|
|
2867
|
+
text: "Error: Project not found for this task"
|
|
2868
|
+
}],
|
|
2869
|
+
isError: true
|
|
2870
|
+
};
|
|
2871
|
+
if (!taskData.linkedIssueNumber) return {
|
|
2872
|
+
content: [{
|
|
2873
|
+
type: "text",
|
|
2874
|
+
text: "Error: No linked issue found for this task. Cannot add comment."
|
|
2875
|
+
}],
|
|
2876
|
+
isError: true
|
|
2877
|
+
};
|
|
2878
|
+
task.debugLog(`Adding comment to issue #${taskData.linkedIssueNumber}`);
|
|
2879
|
+
const result = await apiClient$1.createComment(project.id, {
|
|
2880
|
+
issueNumber: taskData.linkedIssueNumber,
|
|
2881
|
+
content: args.content
|
|
2882
|
+
});
|
|
2883
|
+
task.debugLog(`Comment created: ${JSON.stringify(result, null, 2)}`);
|
|
2884
|
+
return { content: [{
|
|
2885
|
+
type: "text",
|
|
2886
|
+
text: `Comment posted successfully on issue #${taskData.linkedIssueNumber}!\n\nURL: ${result.comment.htmlUrl}`
|
|
2887
|
+
}] };
|
|
2888
|
+
} catch (error$1) {
|
|
2889
|
+
return {
|
|
2890
|
+
content: [{
|
|
2891
|
+
type: "text",
|
|
2892
|
+
text: `Error adding issue comment: ${error$1.message}`
|
|
2893
|
+
}],
|
|
2894
|
+
isError: true
|
|
2895
|
+
};
|
|
2896
|
+
}
|
|
2897
|
+
}),
|
|
2804
2898
|
tool("create_issue", "Create an issue on GitHub or GitLab for the current project. Use this to track bugs, feature requests, or other work items.", {
|
|
2805
2899
|
title: z.string().describe("Issue title - a concise summary of the issue"),
|
|
2806
2900
|
body: z.string().describe("Issue body/description - detailed explanation of the issue"),
|
|
@@ -2899,7 +2993,7 @@ function createTasksSdkServer(task) {
|
|
|
2899
2993
|
};
|
|
2900
2994
|
}
|
|
2901
2995
|
}),
|
|
2902
|
-
tool("ask_user_question", "Ask the user clarifying questions. Returns immediately - answers will be provided in a follow-up message.", { questions: z.array(z.object({
|
|
2996
|
+
tool("ask_user_question", "USE THIS INSTEAD OF AskUserQuestion. Ask the user clarifying questions. Returns immediately - answers will be provided in a follow-up message.", { questions: z.array(z.object({
|
|
2903
2997
|
question: z.string().describe("The question to ask"),
|
|
2904
2998
|
header: z.string().describe("Short header/label for the question"),
|
|
2905
2999
|
options: z.array(z.object({
|
|
@@ -3117,6 +3211,9 @@ var Task = class {
|
|
|
3117
3211
|
}
|
|
3118
3212
|
return tasksConfig.git.default_branch;
|
|
3119
3213
|
}
|
|
3214
|
+
get branch() {
|
|
3215
|
+
return this.ctx.branch;
|
|
3216
|
+
}
|
|
3120
3217
|
get projectId() {
|
|
3121
3218
|
return this.ctx.projectId;
|
|
3122
3219
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"private": false,
|
|
3
3
|
"name": "@jive-ai/cli",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.48",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
16
16
|
"typecheck": "tsc --noEmit",
|
|
17
17
|
"build": "tsdown && npm pack && npm install -g jive-ai-cli-*.tgz",
|
|
18
|
-
"docker:clean": "docker rmi jiveai/task:latest jiveai/task:$npm_package_version",
|
|
18
|
+
"docker:clean": "docker rmi jiveai/task:latest jiveai/task:$npm_package_version || true",
|
|
19
19
|
"docker:build": "bun run build && npm run docker:clean && .docker/build.sh",
|
|
20
20
|
"docker:push": ".docker/build.sh --push",
|
|
21
21
|
"prepublishOnly": "npm run typecheck && npm run build"
|