@jive-ai/cli 0.0.35 → 0.0.37
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/README.md +6 -1
- package/dist/index.mjs +43 -107
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,12 +47,17 @@ You can extend the Jive task runner image to add custom tools or dependencies:
|
|
|
47
47
|
FROM jiveai/task:latest
|
|
48
48
|
|
|
49
49
|
# Add your custom dependencies
|
|
50
|
-
RUN
|
|
50
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
51
|
+
python3 \
|
|
52
|
+
python3-pip \
|
|
53
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
51
54
|
|
|
52
55
|
# Install additional tools
|
|
53
56
|
RUN pip install --break-system-packages black ruff
|
|
54
57
|
```
|
|
55
58
|
|
|
59
|
+
**Note:** The base image is Debian-based (bookworm-slim), so use `apt-get` for package management.
|
|
60
|
+
|
|
56
61
|
## Publishing the Docker Image (Maintainers)
|
|
57
62
|
|
|
58
63
|
### One-Time Setup
|
package/dist/index.mjs
CHANGED
|
@@ -2566,6 +2566,7 @@ const cliQueries = {
|
|
|
2566
2566
|
directory
|
|
2567
2567
|
repository
|
|
2568
2568
|
branch
|
|
2569
|
+
defaultBranch
|
|
2569
2570
|
gitAuth {
|
|
2570
2571
|
privateKey
|
|
2571
2572
|
repositoryUrl
|
|
@@ -2573,6 +2574,12 @@ const cliQueries = {
|
|
|
2573
2574
|
method
|
|
2574
2575
|
}
|
|
2575
2576
|
permissionMode
|
|
2577
|
+
settings {
|
|
2578
|
+
model
|
|
2579
|
+
environmentVariables
|
|
2580
|
+
betaFlags
|
|
2581
|
+
permissionMode
|
|
2582
|
+
}
|
|
2576
2583
|
}
|
|
2577
2584
|
sessionId
|
|
2578
2585
|
}
|
|
@@ -2925,7 +2932,15 @@ var ApiClient = class {
|
|
|
2925
2932
|
directory: t$2.ctx.directory,
|
|
2926
2933
|
repository: t$2.ctx.repository,
|
|
2927
2934
|
branch: t$2.ctx.branch,
|
|
2928
|
-
|
|
2935
|
+
defaultBranch: t$2.ctx.defaultBranch,
|
|
2936
|
+
gitAuth: t$2.ctx.gitAuth,
|
|
2937
|
+
permissionMode: t$2.ctx.permissionMode,
|
|
2938
|
+
settings: {
|
|
2939
|
+
model: t$2.ctx.settings.model,
|
|
2940
|
+
environmentVariables: t$2.ctx.settings.environmentVariables,
|
|
2941
|
+
betaFlags: t$2.ctx.settings.betaFlags,
|
|
2942
|
+
permissionMode: t$2.ctx.settings.permissionMode
|
|
2943
|
+
}
|
|
2929
2944
|
},
|
|
2930
2945
|
sessionId: t$2.sessionId
|
|
2931
2946
|
})) };
|
|
@@ -3342,20 +3357,14 @@ async function spawnTaskDocker(ctx, config$2, opts) {
|
|
|
3342
3357
|
envVars.push("-e", `GIT_USERNAME=${ctx.gitAuth.username}`);
|
|
3343
3358
|
envVars.push("-e", `GIT_PASSWORD=${ctx.gitAuth.token}`);
|
|
3344
3359
|
}
|
|
3345
|
-
const useSysbox = process.env.JIVE_USE_SYSBOX !== "false";
|
|
3346
3360
|
const dockerArgs = [
|
|
3347
3361
|
"run",
|
|
3348
3362
|
"--rm",
|
|
3349
|
-
"-i"
|
|
3363
|
+
"-i",
|
|
3364
|
+
"--runtime",
|
|
3365
|
+
"sysbox-runc"
|
|
3350
3366
|
];
|
|
3351
|
-
|
|
3352
|
-
dockerArgs.push("--runtime", "sysbox-runc");
|
|
3353
|
-
console.log(chalk.dim("Using Sysbox runtime for isolated Docker-in-Docker"));
|
|
3354
|
-
} else {
|
|
3355
|
-
dockerArgs.push("-v", "/var/run/docker.sock:/var/run/docker.sock");
|
|
3356
|
-
dockerArgs.push("--user", "root");
|
|
3357
|
-
console.log(chalk.yellow("Warning: Using Docker socket mount (no isolation). Set JIVE_USE_SYSBOX=true on Linux for secure mode."));
|
|
3358
|
-
}
|
|
3367
|
+
console.log(chalk.dim("Using Sysbox runtime for isolated Docker-in-Docker"));
|
|
3359
3368
|
dockerArgs.push("--network", "bridge");
|
|
3360
3369
|
if (isDevMode) {
|
|
3361
3370
|
dockerArgs.push("--add-host", "host.docker.internal:host-gateway");
|
|
@@ -3421,7 +3430,7 @@ async function createGraphQLClient() {
|
|
|
3421
3430
|
|
|
3422
3431
|
//#endregion
|
|
3423
3432
|
//#region package.json
|
|
3424
|
-
var version = "0.0.
|
|
3433
|
+
var version = "0.0.37";
|
|
3425
3434
|
|
|
3426
3435
|
//#endregion
|
|
3427
3436
|
//#region src/runner/index.ts
|
|
@@ -3531,6 +3540,12 @@ var TaskRunner = class {
|
|
|
3531
3540
|
method
|
|
3532
3541
|
}
|
|
3533
3542
|
permissionMode
|
|
3543
|
+
settings {
|
|
3544
|
+
model
|
|
3545
|
+
environmentVariables
|
|
3546
|
+
betaFlags
|
|
3547
|
+
permissionMode
|
|
3548
|
+
}
|
|
3534
3549
|
}
|
|
3535
3550
|
}
|
|
3536
3551
|
`);
|
|
@@ -3558,7 +3573,13 @@ var TaskRunner = class {
|
|
|
3558
3573
|
branch: data.taskContext.branch,
|
|
3559
3574
|
defaultBranch: data.taskContext.defaultBranch,
|
|
3560
3575
|
gitAuth: auth || void 0,
|
|
3561
|
-
permissionMode: data.taskContext.permissionMode
|
|
3576
|
+
permissionMode: data.taskContext.permissionMode,
|
|
3577
|
+
settings: {
|
|
3578
|
+
model: data.taskContext.settings.model,
|
|
3579
|
+
environmentVariables: data.taskContext.settings.environmentVariables,
|
|
3580
|
+
betaFlags: data.taskContext.settings.betaFlags,
|
|
3581
|
+
permissionMode: data.taskContext.settings.permissionMode
|
|
3582
|
+
}
|
|
3562
3583
|
};
|
|
3563
3584
|
} catch (error$1) {
|
|
3564
3585
|
console.error(error$1);
|
|
@@ -3821,7 +3842,7 @@ async function queryClaude(prompt, mcpServer, opts) {
|
|
|
3821
3842
|
const credentials = await getCredentials();
|
|
3822
3843
|
if (!credentials?.anthropicApiKey) throw new Error("Anthropic API key not found in credentials JSON");
|
|
3823
3844
|
process.env.ANTHROPIC_API_KEY = credentials.anthropicApiKey;
|
|
3824
|
-
const { defaultModel, environmentVariables, betaFlags } =
|
|
3845
|
+
const { model: defaultModel, environmentVariables, betaFlags } = task.getSettings();
|
|
3825
3846
|
for (const [key, value$1] of Object.entries(environmentVariables)) process.env[key] = value$1;
|
|
3826
3847
|
debugLog(`[Task ${task.id}] Querying Claude with permission mode: ${permissionMode}`);
|
|
3827
3848
|
debugLog(`[Task ${task.id}] Using model: ${defaultModel}`);
|
|
@@ -3864,49 +3885,6 @@ async function queryClaude(prompt, mcpServer, opts) {
|
|
|
3864
3885
|
}
|
|
3865
3886
|
});
|
|
3866
3887
|
}
|
|
3867
|
-
async function getTaskClaudeSettings(opts) {
|
|
3868
|
-
const { projectId } = opts;
|
|
3869
|
-
let teamSettings;
|
|
3870
|
-
let projectSettings;
|
|
3871
|
-
try {
|
|
3872
|
-
const client = await getGraphQLClient();
|
|
3873
|
-
const projectData = await client.request(cliQueries.Project, { id: projectId });
|
|
3874
|
-
if (projectData.project) {
|
|
3875
|
-
const projectSettingsData = projectData.project?.settings;
|
|
3876
|
-
if (projectSettingsData) projectSettings = {
|
|
3877
|
-
defaultModel: projectSettingsData.defaultModel,
|
|
3878
|
-
environmentVariables: projectSettingsData.environmentVariables,
|
|
3879
|
-
betaFlags: projectSettingsData.betaFlags
|
|
3880
|
-
};
|
|
3881
|
-
if (projectData.project.team) {
|
|
3882
|
-
const teamClaude = (await client.request(cliQueries.Team, { id: projectData.project.team.id })).team?.settings?.claude;
|
|
3883
|
-
if (teamClaude) teamSettings = {
|
|
3884
|
-
defaultModel: teamClaude.defaultModel,
|
|
3885
|
-
environmentVariables: teamClaude.environmentVariables,
|
|
3886
|
-
betaFlags: teamClaude.betaFlags
|
|
3887
|
-
};
|
|
3888
|
-
}
|
|
3889
|
-
}
|
|
3890
|
-
} catch (error$1) {
|
|
3891
|
-
debugLog(`[Task] Failed to fetch settings, using defaults: ${error$1}`);
|
|
3892
|
-
}
|
|
3893
|
-
const defaultModel = projectSettings?.defaultModel || teamSettings?.defaultModel || "sonnet";
|
|
3894
|
-
const teamEnvVars = teamSettings?.environmentVariables || {};
|
|
3895
|
-
const projectEnvVars = projectSettings?.environmentVariables || {};
|
|
3896
|
-
const environmentVariables = {
|
|
3897
|
-
...teamEnvVars,
|
|
3898
|
-
...projectEnvVars
|
|
3899
|
-
};
|
|
3900
|
-
const betaFlags = [...teamSettings?.betaFlags || [], ...projectSettings?.betaFlags || []];
|
|
3901
|
-
debugLog(`[Task] Default model: ${defaultModel}`);
|
|
3902
|
-
debugLog(`[Task] Environment variables: ${Object.keys(environmentVariables).join(", ")}`);
|
|
3903
|
-
debugLog(`[Task] Beta flags: ${betaFlags.join(", ")}`);
|
|
3904
|
-
return {
|
|
3905
|
-
defaultModel,
|
|
3906
|
-
environmentVariables,
|
|
3907
|
-
betaFlags
|
|
3908
|
-
};
|
|
3909
|
-
}
|
|
3910
3888
|
function mapPermissionMode(permissionMode) {
|
|
3911
3889
|
switch (permissionMode) {
|
|
3912
3890
|
case "DEFAULT": return "default";
|
|
@@ -4317,6 +4295,13 @@ var Task = class {
|
|
|
4317
4295
|
get projectId() {
|
|
4318
4296
|
return this.ctx.projectId;
|
|
4319
4297
|
}
|
|
4298
|
+
/**
|
|
4299
|
+
* Get task settings (model, environment variables, beta flags, permission mode).
|
|
4300
|
+
* Settings are inherited from team/project at task creation time and can be overridden per-task.
|
|
4301
|
+
*/
|
|
4302
|
+
getSettings() {
|
|
4303
|
+
return this.ctx.settings;
|
|
4304
|
+
}
|
|
4320
4305
|
constructor(ctx) {
|
|
4321
4306
|
this.id = ctx.taskId;
|
|
4322
4307
|
this.ctx = ctx;
|
|
@@ -5574,42 +5559,6 @@ async function initCommand() {
|
|
|
5574
5559
|
}
|
|
5575
5560
|
}
|
|
5576
5561
|
|
|
5577
|
-
//#endregion
|
|
5578
|
-
//#region src/lib/git-utils.ts
|
|
5579
|
-
/**
|
|
5580
|
-
* Normalizes a git URL to a canonical form for comparison.
|
|
5581
|
-
* Handles SSH, HTTPS, with/without .git suffix, trailing slashes.
|
|
5582
|
-
* Returns format: github.com/owner/repo (lowercase)
|
|
5583
|
-
*/
|
|
5584
|
-
function normalizeGitUrl(url) {
|
|
5585
|
-
if (!url) return "";
|
|
5586
|
-
let normalized = url.trim();
|
|
5587
|
-
normalized = normalized.replace(/\.git$/, "");
|
|
5588
|
-
normalized = normalized.replace(/\/+$/, "");
|
|
5589
|
-
const sshMatch = normalized.match(/^git@([^:]+):(.+)$/);
|
|
5590
|
-
if (sshMatch) {
|
|
5591
|
-
const [, host, path$2] = sshMatch;
|
|
5592
|
-
normalized = `${host}/${path$2}`;
|
|
5593
|
-
}
|
|
5594
|
-
const httpsMatch = normalized.match(/^https?:\/\/([^/]+)\/(.+)$/);
|
|
5595
|
-
if (httpsMatch) {
|
|
5596
|
-
const [, host, path$2] = httpsMatch;
|
|
5597
|
-
normalized = `${host.includes("@") ? host.split("@")[1] : host}/${path$2}`;
|
|
5598
|
-
}
|
|
5599
|
-
const gitMatch = normalized.match(/^git:\/\/([^/]+)\/(.+)$/);
|
|
5600
|
-
if (gitMatch) {
|
|
5601
|
-
const [, host, path$2] = gitMatch;
|
|
5602
|
-
normalized = `${host}/${path$2}`;
|
|
5603
|
-
}
|
|
5604
|
-
return normalized.toLowerCase();
|
|
5605
|
-
}
|
|
5606
|
-
/**
|
|
5607
|
-
* Compares two git URLs to see if they point to the same repository.
|
|
5608
|
-
*/
|
|
5609
|
-
function gitUrlsMatch(url1, url2) {
|
|
5610
|
-
return normalizeGitUrl(url1) === normalizeGitUrl(url2);
|
|
5611
|
-
}
|
|
5612
|
-
|
|
5613
5562
|
//#endregion
|
|
5614
5563
|
//#region src/commands/task.ts
|
|
5615
5564
|
const execAsync = promisify(exec);
|
|
@@ -5639,27 +5588,14 @@ async function resumeCommand(taskId) {
|
|
|
5639
5588
|
}
|
|
5640
5589
|
const { task, project } = taskData;
|
|
5641
5590
|
spinner.text = "Verifying repository...";
|
|
5642
|
-
let localRemoteUrl;
|
|
5643
5591
|
try {
|
|
5644
5592
|
const { stdout } = await execAsync("git remote get-url origin");
|
|
5645
|
-
|
|
5593
|
+
stdout.trim();
|
|
5646
5594
|
} catch (error$1) {
|
|
5647
5595
|
spinner.fail(chalk.red("Current directory is not a git repository"));
|
|
5648
5596
|
console.error(chalk.dim("Run this command from within the project repository"));
|
|
5649
5597
|
process.exit(1);
|
|
5650
5598
|
}
|
|
5651
|
-
const projectRepoUrl = project.gitRepoUrl;
|
|
5652
|
-
if (!projectRepoUrl) {
|
|
5653
|
-
spinner.fail(chalk.red("Task project has no repository URL configured"));
|
|
5654
|
-
process.exit(1);
|
|
5655
|
-
}
|
|
5656
|
-
if (!gitUrlsMatch(localRemoteUrl, projectRepoUrl)) {
|
|
5657
|
-
spinner.fail(chalk.red("Repository mismatch"));
|
|
5658
|
-
console.error(chalk.dim(`Local repository: ${localRemoteUrl}`));
|
|
5659
|
-
console.error(chalk.dim(`Project repository: ${projectRepoUrl}`));
|
|
5660
|
-
console.error(chalk.dim("\nRun this command from within the correct project directory"));
|
|
5661
|
-
process.exit(1);
|
|
5662
|
-
}
|
|
5663
5599
|
spinner.text = "Fetching session data...";
|
|
5664
5600
|
const sessions = await apiClient$1.getTaskSessions(id);
|
|
5665
5601
|
if (!sessions || sessions.length === 0) {
|