@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.
Files changed (3) hide show
  1. package/README.md +6 -1
  2. package/dist/index.mjs +43 -107
  3. 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 apk add --no-cache python3 py3-pip
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
- gitAuth: t$2.ctx.gitAuth
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
- if (useSysbox) {
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.35";
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 } = await getTaskClaudeSettings({ projectId: task.projectId.toString() });
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
- localRemoteUrl = stdout.trim();
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) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@jive-ai/cli",
4
- "version": "0.0.35",
4
+ "version": "0.0.37",
5
5
  "main": "index.js",
6
6
  "files": [
7
7
  "dist",