datagrok-tools 6.7.6 → 6.7.8

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.
@@ -66,7 +66,7 @@ Host machine
66
66
  │ │ │ └── <folder>/ ← bind mount of user's repo │ │
67
67
  │ │ ├── /var/run/docker.sock ← host Docker for stand mgmt │ │
68
68
  │ │ ├── entrypoint.sh ← bind-mounted from tools/ │ │
69
- │ │ ├── Claude Code + MCP plugins (Jira, GitHub) │ │
69
+ │ │ ├── Claude Code + MCP plugins (GitHub, Jira) │ │
70
70
  │ │ ├── Playwright + Chrome for testing │ │
71
71
  │ │ └── grok CLI for build/publish/test │ │
72
72
  │ └────────────────────────────────────────────────────────────┘ │
@@ -197,15 +197,25 @@ Based on `node:22-bookworm-slim`. Pre-installed:
197
197
 
198
198
  Runs as **root** in compose (entrypoint drops to `node` user for the main process).
199
199
 
200
- ## MCP plugins: Jira and GitHub
200
+ ## MCP plugins: GitHub and Jira
201
201
 
202
202
  The agent uses MCP plugins to search for similar issues, read context, and update
203
- status. Set tokens in `.env` or the agent will ask interactively on first use.
203
+ status. Tickets are GitHub issues (`datagrok-ai/public`); Jira holds only read-only
204
+ `GROK-NNNNN` history. Set tokens in `.env` or the agent will ask interactively on first use.
204
205
 
205
- ### Jira (Atlassian)
206
+ ### GitHub
206
207
 
207
208
  ```bash
208
209
  # Inside tools-dev, register the MCP server:
210
+ claude mcp add github -s user -- \
211
+ npx -y @modelcontextprotocol/server-github
212
+ ```
213
+
214
+ Requires `GITHUB_TOKEN` in the environment (already passed from `.env`).
215
+
216
+ ### Jira (optional, read-only history)
217
+
218
+ ```bash
209
219
  claude mcp add mcp-atlassian -s user -- \
210
220
  npx -y mcp-atlassian \
211
221
  --jira-url "$JIRA_URL" \
@@ -213,15 +223,6 @@ claude mcp add mcp-atlassian -s user -- \
213
223
  --jira-token "$JIRA_TOKEN"
214
224
  ```
215
225
 
216
- ### GitHub
217
-
218
- ```bash
219
- claude mcp add github -s user -- \
220
- npx -y @modelcontextprotocol/server-github
221
- ```
222
-
223
- Requires `GITHUB_TOKEN` in the environment (already passed from `.env`).
224
-
225
226
  ## Testing
226
227
 
227
228
  ### grok test (Puppeteer-based)
@@ -1,5 +1,5 @@
1
1
 
2
- > datagrok-tools@6.7.6 build /home/runner/work/public/public/tools
2
+ > datagrok-tools@6.7.8 build /home/runner/work/public/public/tools
3
3
  > node build.js
4
4
 
5
5
  Successfully compiled 51 files with Babel.
package/CHANGELOG.md CHANGED
@@ -1,7 +1,12 @@
1
1
  # Datagrok-tools changelog
2
2
 
3
- ## v.next
3
+ ## 6.7.8 (2026-10-13)
4
4
 
5
+ * Fixed `grok api` (and every command other than `grok s`) exiting with code 1 and its usage text in 6.7.7: the new `--send-email` flag reached every command as `send-email: false`, which `grok api` rejected as an unknown option
6
+
7
+ ## 6.7.7 (2026-10-09)
8
+
9
+ * GROK-21156: `grok s users invite [<email>] [--prefix <P>] [--send-email]`: invites a user and prints a link that logs them in (no email sent; the email may be omitted); `--prefix` starts the code with `<P>`; `--send-email` mails the invitation instead
5
10
  * `grok test --skip-gc` launches the browser without `--expose-gc`, so the test runner skips its garbage collection after every test; a suite of small unit tests runs several times faster (ComputeUtils driver tests: 92 s to 19 s)
6
11
  * `grok setup` installs corepack when it is missing instead of asking for it by hand: Node 25 no longer bundles corepack, so every fresh checkout on current Node stopped at that step
7
12
  * `grok setup` also removes the `.js`/`.d.ts` files the npm-era tsc emitted beside js-api and library sources: the workspace emits into `dist/`, and a leftover `js-api/grok.js` shadowed the `grok` command in cmd.exe
package/CLAUDE.md CHANGED
@@ -220,7 +220,7 @@ Based on `node:22-bookworm-slim`. Pre-installed:
220
220
  | `demo` | + world, test_db, northwind |
221
221
  | `full` | + grok_spawner, JKG, demo DBs |
222
222
 
223
- See `.devcontainer/PACKAGES_DEV.md` for detailed usage docs, architecture diagram, MCP plugin setup (Jira/GitHub), and troubleshooting.
223
+ See `.devcontainer/PACKAGES_DEV.md` for detailed usage docs, architecture diagram, MCP plugin setup (GitHub/Jira), and troubleshooting.
224
224
 
225
225
  ### `grok server` / `grok s` Command
226
226
 
package/GROK_S.md CHANGED
@@ -16,6 +16,7 @@ browser or a logged-in session.
16
16
  |-------------------------------------------------------------|--------------------------------------------------------|
17
17
  | Create / update a user | `grok s users save --json user.json` |
18
18
  | Block / unblock a user | `grok s users block <login>` / `users unblock <login>` |
19
+ | Invite a user, get a login link | `grok s users invite [<email>] [--prefix <P>]` |
19
20
  | Create / update a group | `grok s groups save --json group.json` |
20
21
  | Add or remove users in a group | `grok s groups add-members <group> <user>...` |
21
22
  | List members of a group | `grok s groups list-members <group>` |
@@ -165,8 +166,17 @@ personal groups.
165
166
  ```bash
166
167
  grok s users block alice.mendel # accept login, UUID, or namespace:name
167
168
  grok s users unblock alice.mendel
169
+ grok s users invite alice@corp.com # prints a login link; no email is sent
170
+ grok s users invite # same, for an account with no email
171
+ grok s users invite --prefix ALEX- # code starts with ALEX- (letters, digits, - and _, up to 32)
172
+ grok s users invite alice@corp.com --send-email # mail the invitation instead
168
173
  ```
169
174
 
175
+ `users invite` creates the user in state `new` and prints `<server>?inviteCode=<code>`. The
176
+ link logs straight in as that user, every time, for a year. Inviting the same email again
177
+ prints a new link, and the earlier ones keep working. An account that has already been used
178
+ cannot be sent a link.
179
+
170
180
  Both commands resolve the argument to a full user record first, so the server receives
171
181
  the entire object (matching the Python client's `grok.users.block(user)`). Blocking
172
182
  flips `status` to `Blocked` and terminates active sessions; unblocking restores `Active`.
@@ -616,9 +626,12 @@ entities shared with that account, and the target's own users never get their co
616
626
 
617
627
  ```bash
618
628
  grok s pull --since 10y --type project,connection,query,script,group,layout --out ./bundle --host dev --admin
619
- grok s push ./bundle --host prod --admin --on-conflict skip
629
+ grok s push ./bundle --host prod --admin --on-conflict adopt
620
630
  ```
621
631
 
632
+ `adopt` keeps one copy of what both instances already have, such as shared groups and spaces;
633
+ `skip` would leave them alone and fail everything in the bundle that points at them.
634
+
622
635
  **Move a whole instance one space at a time.** Placement is exclusive on the server — one project
623
636
  holding an entity takes it from every other — so a single bundle carrying every space has its
624
637
  projects competing, and a stand-sized push spends its time taking rows back off each other. Scoped
package/README.md CHANGED
@@ -106,7 +106,8 @@ For more information on configuring connections, refer to the [Connections](http
106
106
  `config.yaml`): `grok report fetch <instance> <number>` downloads the report zip, `grok report read
107
107
  <zip|json|instance number>` prints one normalized JSON object (flags `--extract-screenshot`,
108
108
  `--extract-d42`, `--extract-client-log`), `grok report resolve <instance> <number>` marks it resolved.
109
- `ticket`, `comment`, `label`, `attach` talk to JIRA with `JIRA_TOKEN`. See `grok report --help`.
109
+ `ticket`, `comment`, `label`, `attach` talk to JIRA with `JIRA_TOKEN`; porting them to GitHub Issues
110
+ is pending. See `grok report --help`.
110
111
  - `check` checks package content (function signatures, import statements of external modules,
111
112
  etc.). The check is also run during package publication.
112
113
  - `init` modifies a package template by adding config files for linters, IDE, and so on
@@ -111,6 +111,7 @@ async function server(argv) {
111
111
  if (entity === 'groups' && (verb === 'list-members' || verb === 'list-memberships')) return await handleGroupListMembers(dapi, verb, rest, argv, output);
112
112
  if (entity === 'users' && verb === 'block') return await handleUserBlock(dapi, rest, output);
113
113
  if (entity === 'users' && verb === 'unblock') return await handleUserUnblock(dapi, rest, output);
114
+ if (entity === 'users' && verb === 'invite') return await handleUserInvite(dapi, rest, argv, output);
114
115
  if (entity === 'tables' && verb === 'download') return await handleTablesDownload(dapi, rest, argv, output);
115
116
  if (entity === 'tables' && verb === 'upload') return await handleTablesUpload(dapi, rest, output);
116
117
  if (entity === 'packages' && verb === 'install') return await handlePackagesInstall(dapi, rest, argv, output);
@@ -214,6 +215,20 @@ async function handleUserUnblock(dapi, rest, output) {
214
215
  if (output !== 'quiet') console.log(`Unblocked ${user?.login ?? rest[0]}`);
215
216
  return true;
216
217
  }
218
+ async function handleUserInvite(dapi, rest, argv, output) {
219
+ const email = rest[0] !== undefined ? String(rest[0]) : undefined;
220
+ const prefix = argv.prefix !== undefined ? String(argv.prefix) : undefined;
221
+ if (argv['send-email'] && (!email || prefix !== undefined)) {
222
+ (0, _serverOutput.printError)(new Error('Usage: grok s users invite <email> --send-email (no --prefix: only a link has a code)'));
223
+ return false;
224
+ }
225
+ const link = await dapi.users.invite(email, !!argv['send-email'], prefix);
226
+ if (output === 'json') (0, _serverOutput.printOutput)({
227
+ email: email ?? null,
228
+ link: link || null
229
+ }, output);else if (link) console.log(link);else if (output !== 'quiet') console.log(`Invitation sent to ${email}`);
230
+ return true;
231
+ }
217
232
  async function handleTablesDownload(dapi, rest, argv, output) {
218
233
  const name = rest[0];
219
234
  if (!name) {
@@ -949,6 +964,10 @@ Special commands:
949
964
  List parent groups
950
965
  grok s users block <id-or-login> Block a user from the platform
951
966
  grok s users unblock <id-or-login> Unblock a previously blocked user
967
+ grok s users invite [<email>] [--prefix <P>] [--send-email]
968
+ Invite a user; prints a login link (no email sent).
969
+ --prefix starts the code with <P> (e.g. ALEX-);
970
+ --send-email mails the invitation instead
952
971
  grok s tables upload <name> <file.csv|file.d42> Upload a CSV or d42 binary as a Datagrok table
953
972
  grok s tables download <name|Project:Table|id> [-O <file>]
954
973
  Download a table as CSV (stdout by default)
package/bin/grok.js CHANGED
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ // minimist sets every boolean option to false when it is absent, and commands such as `grok api`
3
+ // reject any key they do not expect — so each boolean reaches only the commands that read it.
4
+ const commandBooleans = {dartium: ['test', 'stresstest'], 'send-email': ['server', 's']};
2
5
  const argv = require('minimist')(process.argv.slice(2), {
3
6
  alias: {k: 'key', h: 'help', r: 'recursive'},
4
- boolean: ['dartium'],
7
+ boolean: Object.keys(commandBooleans),
5
8
  // keep versions verbatim — minimist would coerce '1.10' to the number 1.1
6
- string: ['version'],
9
+ string: ['version', 'prefix'],
7
10
  });
8
11
  // minimist maps `--no-retry` to `{retry: false}`, so the `args['no-retry']` checks in
9
12
  // test.ts / playwright-runner.ts never fired and `--no-retry` was silently ignored
@@ -59,8 +62,9 @@ function printUsage(command) {
59
62
  }
60
63
 
61
64
  const command = argv['_'][0];
62
- if (command !== 'test' && command !== 'stresstest')
63
- delete argv.dartium;
65
+ for (const [flag, owners] of Object.entries(commandBooleans))
66
+ if (!owners.includes(command))
67
+ delete argv[flag];
64
68
  if (command in commands) {
65
69
  try {
66
70
  if (argv['help']) {
@@ -595,6 +595,20 @@ class NodeUsersDataSource extends NodeHttpDataSource {
595
595
  async unblock(user) {
596
596
  await this.client.post('/public/v1/users/unblock', user);
597
597
  }
598
+
599
+ /**
600
+ * Creates the invitee (status `new`) and returns a link that logs them in, sending no email; the
601
+ * email may be omitted, and [prefix] goes in front of the link's code. With [sendEmail] the
602
+ * server mails the invitation and returns '' instead.
603
+ */
604
+ async invite(email, sendEmail = false, prefix) {
605
+ return this.client.post(`/users/invite${buildQuery({
606
+ email: email ?? '',
607
+ target: 'Datagrok',
608
+ link: sendEmail ? undefined : true,
609
+ prefix
610
+ })}`);
611
+ }
598
612
  }
599
613
  exports.NodeUsersDataSource = NodeUsersDataSource;
600
614
  class NodeConnectionsDataSource extends NodeHttpDataSource {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/datagrok-ai/public.git"
6
6
  },
7
- "version": "6.7.6",
7
+ "version": "6.7.8",
8
8
  "description": "Utility to upload and publish packages to Datagrok",
9
9
  "homepage": "https://github.com/datagrok-ai/public/tree/master/tools#readme",
10
10
  "dependencies": {
@@ -90,7 +90,7 @@
90
90
  "update:ivp-parser": "esbuild plugins/ivp-parser.entry.mjs --bundle --format=cjs --platform=node --alias:diff-grok=../libraries/compute-utils/node_modules/diff-grok --outfile=plugins/ivp-parser.bundle.cjs",
91
91
  "debug-source-map": "node build.js --source-maps",
92
92
  "test": "vitest run --project unit",
93
- "test:server": "vitest run --project unit bin/__tests__/node-dapi bin/__tests__/server bin/__tests__/migrate bin/__tests__/keypair",
93
+ "test:server": "vitest run --project unit bin/__tests__/node-dapi bin/__tests__/server bin/__tests__/migrate bin/__tests__/keypair bin/__tests__/grok-cli",
94
94
  "test:watch": "vitest --project unit",
95
95
  "test:integration": "vitest run --project integration",
96
96
  "test:all": "vitest run"