datagrok-tools 6.0.2 → 6.0.4

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.
@@ -14,7 +14,9 @@
14
14
  "Bash(MSYS_NO_PATHCONV=1 docker exec dg-pkg-grok-playground-tools-dev-1 ls -la /workspace/datagrok/packages/awesome 2>&1)",
15
15
  "Bash(MSYS_NO_PATHCONV=1 docker exec dg-pkg-grok-playground-tools-dev-1 ls /workspace/datagrok/packages/awesome/ 2>&1)",
16
16
  "Bash(MSYS_NO_PATHCONV=1 docker exec dg-pkg-grok-playground-tools-dev-1 bash -c 'echo \"=== Symlink ===\" && ls -la /workspace/datagrok/packages/awesome && echo \"=== Package contents ===\" && ls /workspace/datagrok/packages/awesome/ && echo \"=== Public repo root ===\" && ls /workspace/datagrok/js-api /workspace/datagrok/packages /workspace/datagrok/CLAUDE.md 2>&1 | head -5' 2>&1)",
17
- "Bash(grep -r \"tools-dev\" /c/repos/Datagrok --include=\"*\" 2>/dev/null | head -20)"
17
+ "Bash(grep -r \"tools-dev\" /c/repos/Datagrok --include=\"*\" 2>/dev/null | head -20)",
18
+ "Bash(find /c/repos/Datagrok/public/tools/.devcontainer -type f -name \".*\" 2>/dev/null | sort)",
19
+ "Bash(grep -r \"tools-dev\" /c/repos/Datagrok/public/tools/bin --include=\"*.ts\" 2>/dev/null | head -20)"
18
20
  ]
19
21
  }
20
22
  }
@@ -33,17 +33,24 @@ else
33
33
  # plus root files (CLAUDE.md, .claude/, etc.). Much faster than a full clone.
34
34
  sparse_clone() {
35
35
  local branch="$1"
36
- git clone --depth 1 --branch "$branch" --filter=blob:none --no-checkout "$REPO" "$PUBLIC_DIR" \
36
+ # Use init+fetch instead of clone to handle pre-existing directories (e.g. mount points)
37
+ git init "$PUBLIC_DIR" \
38
+ && git -C "$PUBLIC_DIR" remote add origin "$REPO" \
37
39
  && git -C "$PUBLIC_DIR" sparse-checkout set --no-cone \
38
40
  '/*' '!connectors/' '!docker/' '!docusaurus/' '!docusaurus-static/' \
39
- '!environments/' '!hooks/' '!misc/' '!python-api/' '!datagrok-celery-task/' \
40
- '/js-api/**' '/libraries/**' '/help/**' '/packages/**' '/tools/**' \
41
- && git -C "$PUBLIC_DIR" checkout
41
+ '!environments/' '!hooks/' '!misc/' 'python-api/' '!datagrok-celery-task/' \
42
+ '/js-api/**' '/libraries/**' '/help/**/*.md*' '/packages/**' '!help/uploads/**' \
43
+ && git -C "$PUBLIC_DIR" fetch --depth 1 --filter=blob:none origin "$branch" \
44
+ && git -C "$PUBLIC_DIR" checkout -B "$branch" FETCH_HEAD
45
+ }
46
+ # Clear directory contents without removing the dir itself (may be a mount point)
47
+ clear_dir() {
48
+ find "$1" -mindepth 1 -delete 2>/dev/null || rm -rf "$1"/* "$1"/.[!.]* 2>/dev/null || true
42
49
  }
43
50
  echo "[tools-dev] Cloning public repo ($BRANCH, sparse) into $PUBLIC_DIR..."
44
51
  sparse_clone "$BRANCH" \
45
- || { echo "[tools-dev] Branch '$BRANCH' not found, falling back to master."
46
- rm -rf "$PUBLIC_DIR"
52
+ || { echo "[tools-dev] Branch '$BRANCH' clone failed, falling back to master."
53
+ clear_dir "$PUBLIC_DIR"
47
54
  sparse_clone "master"; }
48
55
  echo "[tools-dev] Public repo ready at $PUBLIC_DIR (branch: $(git -C "$PUBLIC_DIR" branch --show-current))."
49
56
  fi
package/CLAUDE.md CHANGED
@@ -148,17 +148,78 @@ Builds packages with `npm install` + `npm run build`. Supports:
148
148
 
149
149
  ### `grok claude` Command
150
150
 
151
- Launches a full Dockerized development environment (Datagrok + PostgreSQL + RabbitMQ + tools-dev container with Claude Code):
151
+ Launches a full Dockerized development environment with Datagrok + Claude Code. The compose configuration is embedded in `claude.ts` — no external files needed.
152
+
152
153
  ```bash
153
- grok claude <project-name> # Create worktree + start containers + launch Claude
154
- grok claude <project-name> --in-place # Use current directory (no worktree)
155
- grok claude <project-name> --keep # Leave containers running on exit
156
- grok claude <project-name> --profile full # Include spawner, JKG, demo DBs
157
- grok claude destroy <project-name> # Tear down containers + worktree
158
- grok claude destroy-all # Destroy all known projects
154
+ grok claude <project> # Create worktree + start containers + launch Claude
155
+ grok claude <project> --in-place # Use current directory (no worktree)
156
+ grok claude <project> --keep # Leave containers running on exit
157
+ grok claude <project> --version 1.22.0 # Pin Datagrok version
158
+ grok claude <project> --profile full # Include spawner, JKG, demo DBs
159
+ grok claude <project> --profile scripting # Include JKG for Python/R/Julia
160
+ grok claude <project> --port 8080 # Fix Datagrok port (default: random free port)
161
+ grok claude <project> --prompt "fix bug" # Pass prompt to Claude Code (-p flag)
162
+ grok claude destroy <project> # Tear down containers + worktree + temp files
163
+ grok claude destroy-all # Destroy all known projects
159
164
  ```
160
165
 
161
- Creates a git worktree at `~/pkg-worktrees/<project-name>`, writes Docker Compose files to `$TMPDIR/dg-pkg-<project-name>`, and auto-detects the Datagrok version (`bleeding-edge` for public repo, `latest` otherwise). Mounts `~/.claude` into the container for credentials.
166
+ **Project name restrictions:** `master` and `main` are rejected.
167
+
168
+ **Lifecycle:**
169
+ 1. Creates git worktree at `~/pkg-worktrees/<project>` (unless `--in-place` or not in a git repo)
170
+ 2. Writes `docker-compose.yaml` + `.env` + optional `docker-compose.override.yaml` to `$TMPDIR/dg-pkg-<project>`
171
+ 3. Runs `docker compose up -d --wait`
172
+ 4. Detects Claude working directory based on repo type (see below)
173
+ 5. Launches `claude --dangerously-skip-permissions` inside the `tools-dev` container
174
+ 6. On exit: stops containers (unless `--keep`)
175
+
176
+ **Version resolution:** `--version` flag > `bleeding-edge` (if inside public repo) > `latest`
177
+
178
+ **Compose services (embedded template):**
179
+ - Always started: `postgres` (pgvector:pg17), `rabbitmq`, `grok_pipe`, `datagrok`, `grok_connect`, `tools-dev`
180
+ - Profile `full`: adds `grok_spawner`
181
+ - Profile `scripting`/`full`: adds `jupyter_kernel_gateway`
182
+ - Profile `demo`/`full`: adds `world`, `test_db`, `northwind` demo databases
183
+
184
+ **Note:** The embedded template in `claude.ts` differs from `.devcontainer/docker-compose.yaml`:
185
+ - Embedded uses separate version vars per service (`DATAGROK_VERSION`, `GROK_CONNECT_VERSION`, `GROK_SPAWNER_VERSION`, `JKG_VERSION`, `TOOLS_DEV_VERSION`); `.devcontainer/` uses a single `DG_VERSION` for all
186
+ - Embedded mounts workspace at `/workspace/repo`; `.devcontainer/` mounts at `/workspace`
187
+ - Embedded has `grok_connect` always-on (no profile); `.devcontainer/` puts it under `profiles: ["full"]`
188
+ - Embedded uses `grok_pipe:latest`; `.devcontainer/` uses `grok_pipe:${DG_VERSION}`
189
+ - Embedded doesn't mount `~/.grok` from host; `.devcontainer/` does
190
+
191
+ **Host config override:** If `~/.claude` (or `CLAUDE_HOME`) is found on the host, a `docker-compose.override.yaml` is generated to bind-mount it into the container. Also mounts `~/.claude.json` if present.
192
+
193
+ **Working directory detection inside container:**
194
+ - Public repo root (has `js-api/`): `/workspace/repo`
195
+ - Monorepo (has `public/js-api/`): `/workspace/repo/public`
196
+ - External repo: `/workspace/datagrok/packages/<folder-name>` (waits up to 600s for entrypoint to clone public repo)
197
+
198
+ #### tools-dev Container (`Dockerfile.pkg_dev`)
199
+
200
+ Based on `node:22-bookworm-slim`. Pre-installed:
201
+ - Google Chrome stable (for Puppeteer), Playwright + Chromium
202
+ - `datagrok-tools` (grok CLI) and `@anthropic-ai/claude-code` (global npm)
203
+ - git, curl, jq, docker CLI
204
+ - Runs as `node` user (UID 1000, added to `docker` group)
205
+
206
+ #### Entrypoint (`entrypoint.sh`)
207
+
208
+ 1. **Repo detection:** checks if `/workspace/repo` is the public repo (has `.git` + `js-api/`) or monorepo (`public/js-api/`)
209
+ 2. **Auto-clone:** if workspace is not the public repo, sparse-clones it to `$DG_PUBLIC_DIR` (default `/workspace/datagrok`) — excludes `connectors/`, `docker/`, `environments/`, `python-api/`, etc. for speed. Branch resolved as: `DG_PUBLIC_BRANCH` > `DG_VERSION` mapped to branch > `master` fallback
210
+ 3. **Workspace linking:** for non-public repos, symlinks `/workspace/repo` into the cloned repo's `packages/` dir and links `.claude`/`CLAUDE.md` at `/workspace/` for context discovery
211
+ 4. **Grok config:** auto-creates `~/.grok/config.yaml` pointing to `http://datagrok:8080/api` with key `admin` (only if config doesn't already exist)
212
+
213
+ #### Profiles
214
+
215
+ | Profile | Additional services |
216
+ |---------|-------------------|
217
+ | (none) | postgres, rabbitmq, grok_pipe, datagrok, grok_connect, tools-dev |
218
+ | `scripting` | + jupyter_kernel_gateway |
219
+ | `demo` | + world, test_db, northwind |
220
+ | `full` | + grok_spawner, JKG, demo DBs |
221
+
222
+ See `.devcontainer/PACKAGES_DEV.md` for detailed usage docs, architecture diagram, MCP plugin setup (Jira/GitHub), and troubleshooting.
162
223
 
163
224
  ## Key Patterns and Conventions
164
225
 
@@ -553,22 +553,24 @@ async function claude(args) {
553
553
  claudeWorkDir = `/workspace/datagrok/packages/${folderName}`;
554
554
  color.info(`Waiting for workspace at ${claudeWorkDir} (streaming container logs)...`);
555
555
 
556
- // Stream container logs so the user can see clone progress
556
+ // Stream container logs so the user can see clone progress (don't inherit stdin)
557
557
  const logsProc = (0, _child_process.spawn)('docker', ['logs', '-f', containerName], {
558
- stdio: 'inherit'
558
+ stdio: ['ignore', 'inherit', 'inherit']
559
559
  });
560
560
  let ready = false;
561
+ const waitStart = Date.now();
561
562
  for (let i = 0; i < 120; i++) {
562
563
  const check = (0, _child_process.spawnSync)('docker', ['exec', containerName, 'test', '-d', claudeWorkDir]);
563
564
  if (check.status === 0) {
564
565
  ready = true;
565
566
  break;
566
567
  }
568
+ if (i > 0 && i % 12 === 0) color.info(`Still waiting for workspace... (${Math.round((Date.now() - waitStart) / 1000)}s elapsed)`);
567
569
  await new Promise(r => setTimeout(r, 5000));
568
570
  }
569
571
 
570
572
  // Stop streaming logs
571
- logsProc.kill();
573
+ logsProc.kill('SIGKILL');
572
574
  if (!ready) {
573
575
  color.warn(`${claudeWorkDir} not available after 600s — falling back to /workspace/repo`);
574
576
  claudeWorkDir = '/workspace/repo';
@@ -7,7 +7,7 @@
7
7
  "datagrok-api": "^1.26.0",
8
8
  "cash-dom": "^8.1.5",
9
9
  "dayjs": "^1.11.13",
10
- "@datagrok-libraries/utils": "^4.6.5"
10
+ "@datagrok-libraries/test": "^1.1.0"
11
11
  },
12
12
  "devDependencies": {
13
13
  "datagrok-tools": "^5.1.5",
@@ -1,4 +1,4 @@
1
- import { runTests, tests, TestContext , initAutoTests as initTests } from '@datagrok-libraries/utils/src/test';
1
+ import { runTests, tests, TestContext , initAutoTests as initTests } from '@datagrok-libraries/test/src/test';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
 
4
4
  export let _package = new DG.Package();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datagrok-tools",
3
- "version": "6.0.2",
3
+ "version": "6.0.4",
4
4
  "description": "Utility to upload and publish packages to Datagrok",
5
5
  "homepage": "https://github.com/datagrok-ai/public/tree/master/tools#readme",
6
6
  "dependencies": {