@gapi/gcli 1.8.239 → 1.8.241

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.
@@ -0,0 +1,31 @@
1
+ ## 2026-10-19 - dedicated-platform-cluster: Cluster scaling, topology, load balancer and health commands (cluster:status, health, scale, autoscale, ...)
2
+
3
+ **Feature:** dedicated-platform-cluster · **Type:** feat
4
+
5
+ - New commands (the dashboard cluster page's actions, same
6
+ cluster-provisioner operations): `cluster:status`, `cluster:health`,
7
+ `cluster:scale-events`, `cluster:cost`, `cluster:scale --workers`,
8
+ `cluster:scale:control-planes --count`, `cluster:multi-node`,
9
+ `cluster:single-node`, `cluster:autoscale` (partial: only the given
10
+ flags change), `cluster:load-balancer --enable|--disable`. All take
11
+ `--cluster <id>` or `--clusterName <name>`; mutations take `--wait`
12
+ (polls until ready; ending in `error` exits non-zero with the reason).
13
+ - `cluster:apply [--spec] [--dry-run] [--yes]`: the `cluster:` section of
14
+ lambforge.yaml / cluster.yaml is now a desired state (new keys
15
+ `controlPlanes`, `loadBalancer`, `autoscale.*`; `singleNode`, `workers`
16
+ as before). It creates the cluster when missing (in the desired shape)
17
+ and otherwise plans and applies topology → workers → control planes →
18
+ load balancer → autoscale, waiting for `ready` between jobs; destructive
19
+ steps need `--yes`. `cluster:create` also passes `controlPlanes` and
20
+ `loadBalancer` from the spec now.
21
+ - Client-side checks mirror the server's bounds (workers 1-10, control
22
+ planes 1/3/5, autoscale ranges) so a bad value fails before any request.
23
+ - `README.md` Private Clusters section, regenerated `README-CLI.md`.
24
+ - **Test:** `npx jest --coverage=false` (71 tests; new
25
+ `test/cluster-scaling.spec.ts`, `test/cluster-apply.spec.ts` (the plan),
26
+ `test/cluster-apply-command.spec.ts` (dry-run, `--yes`, create, refusals)).
27
+ - **Debug:** slice doc `docs/features/dedicated-platform-cluster.md`.
28
+ - **Verification:** jest 71/71; the built binary's `cluster:apply` read a
29
+ real lambforge.yaml and rejected `controlPlanes: 2` before any request; tsc + eslint clean; `npm run build` and
30
+ `--help` checked for every command (`release/index.js` restored after,
31
+ not a release).
@@ -0,0 +1,17 @@
1
+ ## 2026-10-19 - lambforge-agent-skill: README points to the Lambforge agent skill (gcli + mcp:start for AI agents)
2
+
3
+ **Feature:** lambforge-agent-skill · **Type:** docs
4
+
5
+ - README.md "AI agent skill" (under AI Integration): the prompt to paste into
6
+ an agent (https://lambforge.com/skills/platform.md), the manual Claude Code
7
+ install (every file from `files.txt`, `platform.md` copied to `SKILL.md`,
8
+ `claude mcp add --scope user lambforge -- gcli mcp:start`), and what the
9
+ topic files cover. The skill lives in gql-fission `src/skills/` (canonical
10
+ doc there).
11
+ - `docs/features/lambforge-agent-skill.md`: which gcli commands the skill
12
+ quotes - change them, update SKILL.md in the same change.
13
+ - **Test:** none (docs); the commands it lists were checked with
14
+ `node release/index.js <command> --help`.
15
+ - **Debug:** an agent runs a gcli command that fails → compare SKILL.md with
16
+ `gcli <command> --help`.
17
+ - **Verification:** no code change.
@@ -0,0 +1,21 @@
1
+ ## 2026-10-19 - repo: cron:create honours --cron/--triggerName; README brought up to date with every command
2
+
3
+ **Feature:** repo · **Type:** fix
4
+
5
+ - `cron:create` declared `--cron` and `--triggerName` but only read them
6
+ from the spec (`triggers.time` of lambforge.yaml / cron.yaml), so the
7
+ documented `gcli cron:create --lambdaName x --triggerName nightly --cron
8
+ '0 2 * * *'` sent an empty schedule. Flags now win, the spec fills gaps,
9
+ and a missing schedule is a clear error before any request.
10
+ - README: binary install from `releases/latest` (was pinned to v1.8.198);
11
+ `environment:update/delete`, `lambda:list` and a "Schedules (cron)"
12
+ section (the commands were missing); `triggers:` in the unified
13
+ lambforge.yaml; the MCP client URL is `https://<host>/<projectId>/<route>`
14
+ (the `/mcp` suffix was wrong - see example/mcp/lambforge.yaml); the
15
+ declarative cluster section. Every command registered in `src/commands`
16
+ now appears in README.md.
17
+ - **Test:** `npx jest --coverage=false test/cron-create.spec.ts` (flags,
18
+ flags over yaml, missing schedule).
19
+ - **Debug:** a cron with an empty schedule → an older gcli; upgrade.
20
+ - **Verification:** jest 71/71; a script compared the commands registered in
21
+ `src/commands` against README.md (no command missing).
@@ -31,3 +31,5 @@ Outline (drop sections that don't apply):
31
31
  | Feature | Doc | Notes |
32
32
  |---|---|---|
33
33
  | `local-ai-runners` | [local-ai-runners.md](local-ai-runners.md) | `runner:*` commands; canonical doc in graphql-server |
34
+ | `lambforge-agent-skill` | [lambforge-agent-skill.md](lambforge-agent-skill.md) | The agent skill that teaches gcli + `mcp:start`; canonical doc in gql-fission |
35
+ | `dedicated-platform-cluster` | [dedicated-platform-cluster.md](dedicated-platform-cluster.md) | `cluster:status/health/scale/autoscale/...` commands; canonical doc in lambforge-agent |
@@ -0,0 +1,70 @@
1
+ # dedicated-platform-cluster (gcli slice)
2
+
3
+ **Canonical doc:** `lambforge-agent/docs/features/dedicated-platform-cluster.md`
4
+ · **Since:** 2026-10-19 (cluster scaling and health commands)
5
+
6
+ The cluster page's scaling, topology, load balancer and health actions as
7
+ commands (cluster-provisioner operations, the same ones gql-fission's
8
+ `core/services/cluster/*.graphql` use; every one is USER-enabled with
9
+ `isMemberOrProjectOwner`):
10
+
11
+ | Command | Operation |
12
+ |---|---|
13
+ | `cluster:status [--cluster]` | `projectClustersOverview` (status, agent, nodes, load, autoscale, issues) |
14
+ | `cluster:health --cluster` | `clusterHealth(limit: 1)` - latest agent report + nodes |
15
+ | `cluster:scale-events --cluster [--limit]` | `clusterScaleEvents` |
16
+ | `cluster:cost` | `projectClustersOverview` (`monthToDate`, `estimatedMonthlyCostEur`) |
17
+ | `cluster:scale --workers 1-10 [--wait]` | `scaleProjectCluster` |
18
+ | `cluster:scale:control-planes --count 1/3/5 [--wait]` | `scaleControlPlanesProjectCluster` |
19
+ | `cluster:multi-node --workers [--wait]` / `cluster:single-node [--wait]` | `migrateToMultiNodeProjectCluster` / `revertToSingleNodeProjectCluster` |
20
+ | `cluster:autoscale [--enable/--disable] [--min --max --cpuUp --memUp --cpuDown --memDown --samples --cooldown]` | `updateProjectClusterAutoscale` - partial: the server merges it into the stored policy and validates (min <= max, scale-down below scale-up, single-node cannot autoscale) |
21
+ | `cluster:load-balancer --enable/--disable [--wait]` | `enable/disableLoadBalancerProjectCluster` |
22
+ | `cluster:apply [--spec] [--dry-run] [--yes]` | reconciles the `cluster:` section of lambforge.yaml: `projectClusters` (current) → plan → provision / topology / scale / control planes / load balancer / autoscale, one job at a time, waiting for `ready` between them |
23
+
24
+ ## Declarative clusters (`cluster:apply`)
25
+
26
+ `cluster:` keys: `name` (identity), `imageId` / `serverType` / `location`
27
+ (create only), `singleNode`, `workers` (1-10), `controlPlanes` (1/3/5),
28
+ `loadBalancer`, `autoscale.{enabled,minWorkers,maxWorkers,cpuScaleUpPercent,
29
+ memScaleUpPercent,cpuScaleDownPercent,memScaleDownPercent,samplesToScale,
30
+ cooldownMinutes}`. Missing keys are left alone.
31
+
32
+ - `helpers/plan.ts` `planClusterChanges(current, desired)` is pure (unit
33
+ tested): create in the desired shape (workers, control planes, load
34
+ balancer at provision time) then autoscale; otherwise topology → workers
35
+ → control planes → load balancer → autoscale (only the changed keys).
36
+ - `workers` is skipped while `autoscale.enabled` (the autoscaler owns it);
37
+ converting to multi-node already creates the workers.
38
+ - Destructive steps (to single-node, removing the load balancer) need
39
+ `--yes`; without it they are printed and skipped.
40
+ - `validateDesired` mirrors the server's bounds; a cluster that is not
41
+ `ready` is refused (apply again once it settles).
42
+
43
+ ## Files
44
+
45
+ | Path | Responsibility |
46
+ |---|---|
47
+ | `src/commands/cluster/index.ts` | registration (`--cluster` / `--clusterName` on every one) |
48
+ | `src/commands/cluster/{status,health,scale-events,cost,scale,scale-control-planes,autoscale,multi-node,single-node,load-balancer}.ts` | actions |
49
+ | `src/commands/cluster/helpers/cluster-change.ts` | target resolution, int validation, mutate → print → `--wait` (`pollUntilReady`; ends in `error` → non-zero exit) |
50
+ | `src/commands/cluster/types.ts` | local types + selections (newer than `@introspection`) |
51
+ | `src/services/gql-client.ts` | the API calls |
52
+
53
+ ## How to test
54
+
55
+ `npx jest --coverage=false test/cluster-scaling.spec.ts`; manually against a
56
+ project with a private cluster: `gcli cluster:status`, then
57
+ `gcli cluster:scale --clusterName <n> --workers 2 --wait`.
58
+
59
+ ## How to debug
60
+
61
+ | Symptom | Look at |
62
+ |---|---|
63
+ | "Pass --cluster <id> or --clusterName" | no cluster given; `gcli cluster:list` |
64
+ | autoscale refused | the server's message: single-node clusters must `cluster:multi-node` first; external clusters cannot autoscale |
65
+ | `--wait` ends in error | `gcli cluster:list` (status + error), the dashboard's cluster page |
66
+
67
+ ## Not in the CLI yet
68
+
69
+ Resource migration between clusters (`migrateResourcesToCluster` + status /
70
+ retry), Fission options, the cluster agent install/rotate - dashboard only.
@@ -0,0 +1,22 @@
1
+ # lambforge-agent-skill (gcli slice)
2
+
3
+ **Canonical doc:** `gql-fission/docs/features/lambforge-agent-skill.md` ·
4
+ **Since:** 2026-10-19
5
+
6
+ The Lambforge agent skill (entry https://lambforge.com/skills/platform.md,
7
+ topic files next to it; source in gql-fission `src/skills/`) teaches AI
8
+ agents to drive this CLI. `cli.md` lists every command, and `platform.md`,
9
+ `deploy.md`, `events.md`, `clusters.md` and `agents.md` quote gcli exactly:
10
+
11
+ - install: `npm i -g @gapi/gcli` (or `npx @gapi/gcli`);
12
+ - login: the command from Profile -> CLI (`login --token --key --url
13
+ --uploadUrl`), run by the human;
14
+ - `project:list` / `project:use`;
15
+ - `mcp:start` without `--url` (proxy to `<login url>/mcp`, token refresh on
16
+ 401/403) as the MCP server: `claude mcp add --scope user lambforge -- gcli mcp:start`;
17
+ - the `lambda:*`, `environment:*`, `cron:*`, `cluster:*`, `rabbitmq:*`,
18
+ `plugin:*`, `build`, `start` commands and flags it lists.
19
+
20
+ **When you change any of those commands, flags or `mcp:start`, update
21
+ the skill files in gql-fission in the same change** - agents copy it verbatim.
22
+ README.md "AI agent skill" points users to it.
@@ -13,6 +13,8 @@ what lives in gcli.
13
13
  | `gcli runner:list` | Your runners: online, last seen, models |
14
14
  | `gcli runner:models [--id] [--show a,b \| --all \| --none]` | Which models appear in the chat picker; no flag = list |
15
15
  | `gcli runner:delete [--id]` | Delete a runner and revoke its token (default: the saved one) |
16
+ | `gcli runner:daemon:install` (alias `runner:start:daemon`) `[runner:start options] [--service] [--dry-run]` | Resolve/register the runner now (saves `runner.json`), then install + enable + restart a systemd USER unit running `runner:start --ollama <resolved>` (Linux) |
17
+ | `gcli runner:daemon:status` / `:logs` / `:uninstall` | `systemctl --user status`, `journalctl --user -f`, disable --now + remove the unit |
16
18
 
17
19
  Endpoints: `--wsUrl` > `runner.json` > derived from the `gcli login` URL
18
20
  (`https://api.lambforge.com` -> `wss://api.lambforge.com/subscriptions`;
@@ -42,6 +44,15 @@ Ollama: `--ollama` > `$OLLAMA_HOST` (scheme optional, `0.0.0.0` -> `127.0.0.1`)
42
44
  The backend fits every request to it, because Ollama silently drops the
43
45
  oldest messages of a prompt that is too long (see the canonical doc,
44
46
  "Context window").
47
+ - `daemon.ts` - `buildUnit` (pure; systemd quoting; `Restart=always`,
48
+ `RestartPreventExitStatus=78`), `resolveGcliCommand` (node + script, or
49
+ the SEA binary; warns for the npx cache), `SystemdUserService`
50
+ (`systemctl --user` via execFile, never a shell; home dir injectable so
51
+ tests can't touch the real `~/.config`). `daemon-commands.ts` - the
52
+ `runner:daemon:*` actions. Adapted from cli-builder's `SystemctlService`,
53
+ but a USER unit (no root) and no secrets in the unit. `runner:start` exits
54
+ 78 (EX_CONFIG) when the token is refused, so systemd stops instead of
55
+ restart-looping.
45
56
  - `config.ts` (saved runner, URL derivation), `start.ts`, `list.ts`,
46
57
  `models.ts`, `delete.ts`, `index.ts` (command registration), `types.ts`.
47
58
  - `src/services/gql-client.ts` - `createLocalRunner`, `listLocalRunners`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gapi/gcli",
3
- "version": "1.8.239",
3
+ "version": "1.8.241",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/Stradivario/gapi.git"