@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.
- package/.agents/skills/cluster-targeting/SKILL.md +23 -0
- package/.agents/skills/local-ai-runners/SKILL.md +6 -0
- package/README-CLI.md +240 -57
- package/README.md +148 -11
- package/docs/changelog.d/2026-10-11-local-ai-runners-run-the-runner-as-a-systemd-user-service.md +36 -0
- package/docs/changelog.d/2026-10-19-dedicated-platform-cluster-cluster-scaling-topology-load-balancer-and-health-commands-c.md +31 -0
- package/docs/changelog.d/2026-10-19-lambforge-agent-skill-readme-points-to-the-lambforge-agent-skill-gcli-mcp-start-fo.md +17 -0
- package/docs/changelog.d/2026-10-19-repo-cron-create-honours-cron-triggername-readme-brought-up-to-da.md +21 -0
- package/docs/features/README.md +2 -0
- package/docs/features/dedicated-platform-cluster.md +70 -0
- package/docs/features/lambforge-agent-skill.md +22 -0
- package/docs/features/local-ai-runners.md +11 -0
- package/package.json +1 -1
- package/release/index.js +2351 -988
|
@@ -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).
|
package/docs/features/README.md
CHANGED
|
@@ -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`,
|