feat(cli+skill): make documented field UX real + fix skill doc drift

CLI (packages/inkreach-cli):
- new src/lib/field-normalize.ts: type aliases (sel/num/text/mul/…),
  select string-choices -> {name}, compact --fields 'Name:type:choices'
  expansion, smart type inference from --options shape / --name
  (--type now optional), name->ID resolution for foreignTableName /
  linkFieldName / lookupFieldName (incl. link-field foreignTableId
  backfill + unknown-key stripping), rating/number/button required-
  option defaults
- field create: +--description/--lookup-options/--is-lookup
- field update --options + table create --fields route through the
  normalizer; DEFAULT_ENDPOINT :3000 -> :3003
- 20 unit tests (field-normalize.spec.ts, vitest); live-verified:
  string choices, alias, foreignTableName, lookup-by-names, compact
  format, inference (priority->singleSelect, max:5->rating)

Skill docs (.agents/skills/inkreach-teable):
- ports :3000 -> :3003 everywhere (backend real port; :3000 is an
  unrelated container on this host)
- remove dead hr_admin account; note throwaway signup + real admin
- plugin register: actual URL-based flags; document plugin csp
  list/set; view/dashboard install requires config enable first
- field-types.md marked verified-2026-08 (aliases/inference/name
  resolution now implemented + tested)
- development.md: webpack dist/index.js cache trap; PGPASSWORD
  placeholder instead of wrong literal
This commit is contained in:
yeuimu
2026-08-16 05:58:01 +00:00
parent 5a984eb5f8
commit e1a91dfa84
13 changed files with 1015 additions and 34 deletions
+2 -2
View File
@@ -31,7 +31,7 @@ Respond in the user's language. Keep answers concise and action-oriented.
## 1. Prerequisites & Constraints
- All operations use the `inkreach-teable` CLI. Install via `bash scripts/install.sh` (relative to this skill dir) if `inkreach-teable` is not found.
- **Endpoint + token**: configure once with `inkreach-teable auth login --endpoint <url> --token <PAT>`. Default endpoint is `http://localhost:3000`. Verify with `inkreach-teable auth status`.
- **Endpoint + token**: configure once with `inkreach-teable auth login --endpoint <url> --token <PAT>`. Default endpoint is `http://localhost:3003`. Verify with `inkreach-teable auth status`.
- **Getting a PAT**: `inkreach-teable auth token create --name my-cli` (returns the full token **only once**). Scopes default to automation+table+record read/write. Or create via the web UI (Settings → Personal Access Tokens).
- **`--base-id`**: omit if a default was set via `auth login`; CLI uses it automatically. Ask user only if a command fails with MISSING_BASE_ID.
- **`--json` mode**: add `--json` to any command for raw JSON output (for agent parsing).
@@ -82,7 +82,7 @@ Respond in the user's language. Keep answers concise and action-oriented.
```bash
# Configure access (once)
inkreach-teable auth login --endpoint http://localhost:3000 --token <PAT>
inkreach-teable auth login --endpoint http://localhost:3003 --token <PAT>
# Create a table
inkreach-teable table create --name "Tasks" --base-id bseXXX \
@@ -2,6 +2,11 @@
Complete reference of all Teable field types, aliases, option shapes, and smart inference rules.
> ✅ **Verified 2026-08**: aliases, string choices, compact `--fields` format, smart
> inference, and name resolution (`foreignTableName`/`linkFieldName`/`lookupFieldName`)
> are implemented in the CLI (`packages/inkreach-cli/src/lib/field-normalize.ts`)
> and covered by unit tests (`field-normalize.spec.ts`, 20 cases).
---
## Type Overview
@@ -6,7 +6,7 @@ Complete command reference for `inkreach-teable`. Global options apply to all co
| Option | Description |
|--------|-------------|
| `--endpoint <url>` | Backend URL (default `http://localhost:3000`) |
| `--endpoint <url>` | Backend URL (default `http://localhost:3003`) |
| `--token <pat>` | Personal Access Token |
| `--base-id <id>` | Default base id |
| `--json` | Output raw JSON (for agent parsing) |
@@ -46,7 +46,9 @@ inkreach-teable table delete <tableId>
# field (get/update/delete take <tableId> <fieldId> — 2026-08 fix; old /api/field/:id routes never existed)
inkreach-teable field list <tableId>
inkreach-teable field get <tableId> <fieldId>
inkreach-teable field create --table-id <tid> --name <n> --type <t> [--options '<json>']
inkreach-teable field create --table-id <tid> --name <n> [--type <t|alias>] [--options '<json>'] \
[--description <d>] [--lookup-options '<json>'] [--is-lookup]
# --type optional: inferred from --options shape / --name when omitted
inkreach-teable field update <tableId> <fieldId> [--name <n>] [--options '<json>'] # --options goes via convert API
inkreach-teable field visible-choices <tableId> <recordId> <fieldId> # evaluate select-choice visibilityFilter
inkreach-teable field delete <tableId> <fieldId>
@@ -174,8 +176,11 @@ Manage plugins and developer whitelist.
# List plugins registered in the base
inkreach-teable plugin list
# Register a plugin (set runtimeType, positions, logo)
inkreach-teable plugin register --name <name> --positions '["base","panel"]'
# Register a URL-served plugin (runtimeType=url; status published immediately)
# positions: "base"|"panel"|"view"|"dashboard"|"contextMenu"
inkreach-teable plugin register --url <url> --name <name> [--positions '["panel"]'] [--logo <url>] [--description <d>]
# Bundle (upload) plugins use a different flow — see skill guides/tables-fields.md
# or api docs: create kebab-id plugin (developer whitelist) → upload → admin publish.
# Developer whitelist (admin only)
inkreach-teable plugin dev list
@@ -184,12 +189,19 @@ inkreach-teable plugin dev revoke <userIdOrEmail> # remove
# Install / uninstall (creates a base-level mount node)
inkreach-teable plugin install --plugin <pluginId> --name "My Plugin" --position base
# ⚠️ For view/dashboard-position plugins, run `plugin config enable` BEFORE
# install, or the install API returns 403 RESTRICTED_RESOURCE
# 'Plugin is not enabled for this base'.
inkreach-teable plugin installs # list installs in current base
inkreach-teable plugin uninstall --install <installId>
# Enable/disable plugins
inkreach-teable plugin config enable --plugin <pluginId>
inkreach-teable plugin config disable --plugin <pluginId>
# CSP apiOrigins (external origins plugins may fetch)
inkreach-teable plugin csp list
inkreach-teable plugin csp set <pluginId> --origins '["http://192.168.x.x:8001"]'
```
Developer whitelist is admin-only (requires `user.isAdmin=true`). Routes:
@@ -13,10 +13,10 @@ inside NestJS is unstable and will hang or OOM-crash.
| Service | Command | Port | Mode |
|---------|---------|------|------|
| `teable-backend.service` | `node dist/index.js` | `:3000` | `NODE_ENV=production`, `BACKEND_SKIP_NEXT_START=true` |
| `teable-backend.service` | `node dist/index.js` | `:3003` | `NODE_ENV=production`, `BACKEND_SKIP_NEXT_START=true` |
| `teable-frontend.service` | `next start -p 3002 -H 0.0.0.0` | `:3002` | `NODE_ENV=production` |
Users access `:3002`; the backend `:3000` serves the API only.
Users access `:3002`; the backend `:3003` serves the API only.
## Build & Restart
@@ -37,7 +37,7 @@ systemctl --user restart teable-frontend.service
Browser cache is aggressive — hard-refresh (Ctrl+Shift+R) after a rebuild.
### Recover from OOM crash
If `:3000` is unreachable but systemd says `active`:
If `:3003` is unreachable but systemd says `active`:
```bash
systemctl --user stop teable-backend.service
pkill -9 -f 'dist/index.js'
@@ -46,6 +46,13 @@ systemctl --user start teable-backend.service
## Known Gotchas (from real debugging)
### Webpack cache may not rewrite `dist/index.js` after a workspace package rebuild
After rebuilding a workspace package (e.g. `@teable/openapi` dist), `pnpm build` in
`apps/nestjs-backend` can report "compiled successfully" while leaving `dist/index.js`
untouched (node_modules paths are treated as immutable cache inputs). Symptom: backend
behavior unchanged after a code change. Fix: `rm apps/nestjs-backend/dist/index.js`
then rebuild, and verify with `grep '<your-new-string>' dist/index.js`.
### Node v24 fetch drops the Authorization header
The global `fetch()` on Node v24 (undici) drops the `Authorization` request
header in certain cases (redirects, proxies). **Use `node:http`/`node:https`**
@@ -121,16 +128,16 @@ due to the auth-header bug. Test workflows are **deactivated, not deleted**
```bash
# Count workflows by active state
PGPASSWORD=teable psql -h localhost -U teable -d teable -c \
PGPASSWORD=<ask-maintainer> psql -h localhost -U teable -d teable -c \
"SELECT is_active, count(*) FROM workflow WHERE deleted_time IS NULL GROUP BY is_active;"
# Find button fields and their bound workflows
PGPASSWORD=teable psql -h localhost -U teable -d teable -c \
PGPASSWORD=<ask-maintainer> psql -h localhost -U teable -d teable -c \
"SELECT id, name, options->'workflow'->>'id' AS wf_id, options->'workflow'->>'isActive' AS active
FROM field WHERE type='button';"
# Recent executions
PGPASSWORD=teable psql -h localhost -U teable -d teable -c \
PGPASSWORD=<ask-maintainer> psql -h localhost -U teable -d teable -c \
"SELECT id, workflow_id, status, started_at FROM workflow_execution
ORDER BY started_at DESC LIMIT 10;"
```
@@ -8,29 +8,30 @@ endpoint/ports for your own deployment.
| Service | URL / Port | Mode | Purpose |
|---------|-----------|------|---------|
| Backend API | `http://localhost:3000` | production (`NODE_ENV=production`) | REST API, automation engine, websocket |
| Backend API | `http://localhost:3003` | production (`NODE_ENV=production`) | REST API, automation engine, websocket |
| Frontend | `http://localhost:3002` | production | End-user web UI (Next.js) |
| PostgreSQL | `localhost:5432` | — | Database (db: `teable`, user: `teable`) |
| Redis | `localhost:6379` | — | BullMQ queue for automation runs, distributed lock |
- The frontend reads `SOCKET_PORT=3000` from `.env` to point its websocket at the backend. Don't let it fall back to `3001`.
- End users browse `:3002`. The backend `:3000` is the API only (`BACKEND_SKIP_NEXT_START=true` disables the embedded Next server).
- The frontend reads `SOCKET_PORT` from `.env` to point its websocket at the backend — verify it equals the backend port (3003 on this host), not the default 3001.
- End users browse `:3002`. The backend `:3003` is the API only (`BACKEND_SKIP_NEXT_START=true` disables the embedded Next server).
- ⚠️ Port map differs from upstream Teable docs (:3000) — on this host `:3000` is held by an **unrelated container** (`inkreach-web`). Always verify with `ss -tlnp` before assuming.
## Health Checks
```bash
# Backend API up?
curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/api/auth/signin -X POST \
curl -s -o /dev/null -w '%{http_code}' http://localhost:3003/api/auth/signin -X POST \
-H 'Content-Type: application/json' -d '{}' # expect 401 (endpoint exists, bad creds)
# Frontend up?
curl -s -o /dev/null -w '%{http_code}' http://localhost:3002 # expect 307 or 200
# Ports listening?
ss -tlnp | grep -E ':3000|:3002|:5432|:6379'
ss -tlnp | grep -E ':3003|:3002|:5432|:6379'
```
If `:3000` is unreachable but systemd shows `active`, the worker likely OOM-crashed while the `pnpm` parent stayed alive:
If `:3003` is unreachable but systemd shows `active`, the worker likely OOM-crashed while the `pnpm` parent stayed alive:
```bash
systemctl --user stop teable-backend.service
pkill -9 -f 'dist/index.js'
@@ -58,14 +59,15 @@ Note: `auth token list/create` may require a **session** (browser login) rather
### Configure the CLI
```bash
inkreach-teable auth login --endpoint http://localhost:3000 --token <PAT> --base-id bseXXX
inkreach-teable auth login --endpoint http://localhost:3003 --token <PAT> --base-id bseXXX
inkreach-teable auth status # verify
```
## Reference Credentials (local dev)
> Never commit real secrets. The reference dev instance uses:
> - Admin: `hr_admin@xingchen.tech` / (ask maintainer) — for browser login only.
> - ⚠️ The old admin account `hr_admin@xingchen.tech` **no longer exists** (verified 2026-08). Current users: `inkreach@inkreach.pod` (admin) — password: ask maintainer, browser login only.
> - Throwaway accounts for testing can be created via `POST /api/auth/signup` (open on this instance).
> - Base: `bseeZR7yiDNeMPCa4CN` (人事薪资管理) — the test base with ~600 automations.
> - Test table: `tblzPOXQvUruQosKNP5` (has button fields for automation testing).