@flydocs/cli 0.6.0-alpha.10 → 0.6.0-alpha.11

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/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ var CLI_VERSION, CLI_NAME, PACKAGE_NAME, POSTHOG_API_KEY;
15
15
  var init_constants = __esm({
16
16
  "src/lib/constants.ts"() {
17
17
  "use strict";
18
- CLI_VERSION = "0.6.0-alpha.10";
18
+ CLI_VERSION = "0.6.0-alpha.11";
19
19
  CLI_NAME = "flydocs";
20
20
  PACKAGE_NAME = "@flydocs/cli";
21
21
  POSTHOG_API_KEY = "phc_v1MSJTQDFkMS90CBh3mxIz3v8bYCCnKU6v1ir6bz0Xn";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flydocs/cli",
3
- "version": "0.6.0-alpha.10",
3
+ "version": "0.6.0-alpha.11",
4
4
  "type": "module",
5
5
  "description": "FlyDocs AI CLI — install, setup, and manage FlyDocs projects",
6
6
  "bin": {
@@ -59,22 +59,22 @@ All scripts: `python3 .claude/skills/flydocs-cloud/scripts/<script>`
59
59
 
60
60
  ### Workspace Scripts
61
61
 
62
- | Script | Usage | Output |
63
- | ----------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
64
- | `list_providers.py` | (no args) | `[{type, name, connected}]` |
65
- | `set_provider.py` | `<provider_type>` (`linear` or `jira`) | `{success}` — updates relay routing and local config `provider.type` |
66
- | `list_teams.py` | (no args) | `[{id, name, key}]` — returns Linear teams or Jira projects (relay normalizes) |
67
- | `create_team.py` | `--name "..." [--key KEY] [--description "..."] [--parent <team_id>]` | `{id, name, key}` — `--parent` is Linear-only (sub-teams) |
68
- | `set_team.py` | `<team_id>` | `{success}` — updates relay preference and local config; for Jira, sets the active Jira project |
69
- | `list_labels.py` | (no args) | `[{id, name, color}]` — requires team to be set first |
70
- | `set_labels.py` | `--defaults '["a"]' --type-map '{"feature":["F"],...}' \| stdin` | `{success, validated, defaults, typeMap}` — stores label config on relay |
71
- | `list_statuses.py` | (no args) | `{states, currentMapping, flydocsStatuses}` — provider workflow states and current mapping |
72
- | `set_status_mapping.py` | `--auto \| --mapping '{"BACKLOG":"Backlog",...}' \| stdin` | `{success, mapping, matched, total}` — stores status mapping on relay |
73
- | `set_identity.py` | `<provider> <provider-user-id>` | `{success, provider, providerId}` — binds provider user ID for `--mine` resolution |
74
- | `set_preferences.py` | `[--workspace ID] [--assignee self\|ID] [--display JSON]` | `{success, preferences}` — no flags = GET current; with flags = POST update |
75
- | `get_estimate_scale.py` | (no args) | `{scale, type}` — provider's valid estimate values (fixed or freeform) |
76
- | `refresh_labels.py` | `[--fix]` | `{valid, stale, details}` — validates config label IDs against relay; `--fix` updates stale IDs |
77
- | `validate_setup.py` | (no args) | `{valid, checks, missing[]}` — validates workspace config, caches result, sets setupComplete |
62
+ | Script | Usage | Output |
63
+ | ----------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
64
+ | `list_providers.py` | (no args) | `[{type, name, connected}]` |
65
+ | `set_provider.py` | `<provider_type>` (`linear` or `jira`) | `{success}` — updates relay routing and local config `provider.type` |
66
+ | `list_teams.py` | (no args) | `[{id, name, key}]` — returns Linear teams or Jira projects (relay normalizes) |
67
+ | `create_team.py` | `--name "..." [--key KEY] [--description "..."] [--parent <team_id>]` | `{id, name, key}` — `--parent` is Linear-only (sub-teams) |
68
+ | `set_team.py` | `<team_id>` | `{success}` — updates relay preference and local config; for Jira, sets the active Jira project |
69
+ | `list_labels.py` | (no args) | `[{id, name, color}]` — requires team to be set first |
70
+ | `set_labels.py` | `--defaults '["a"]' --type-map '{"feature":["F"],...}' \| stdin` | `{success, validated, defaults, typeMap}` — stores label config on relay |
71
+ | `list_statuses.py` | (no args) | `{states, currentMapping, flydocsStatuses}` — provider workflow states and current mapping |
72
+ | `set_status_mapping.py` | `--auto \| --mapping '{"BACKLOG":"Backlog",...}' \| stdin` | `{success, mapping, matched, total}` — stores status mapping on relay |
73
+ | `set_identity.py` | `<provider> <provider-user-id>` | `{success, provider, providerId}` — binds provider user ID for `--mine` resolution |
74
+ | `set_preferences.py` | `[--workspace ID] [--assignee self\|ID] [--display JSON]` | `{success, preferences}` — no flags = GET current; with flags = POST update |
75
+ | `get_estimate_scale.py` | (no args) | `{scale, type}` — provider's valid estimate values (fixed or freeform) |
76
+ | `refresh_labels.py` | `[--fix]` | `{valid, stale, details}` — validates config label IDs against relay; `--fix` updates stale IDs |
77
+ | `validate_setup.py` | (no args) | `{valid, checks, passed[], missing[], warnings[]}` — reads relay validation, caches result, sets setupComplete |
78
78
 
79
79
  ### Script Notes
80
80
 
@@ -117,7 +117,19 @@ Relay errors include `code` and optional `provider_error` for debugging.
117
117
 
118
118
  ## Configuration
119
119
 
120
- Reads from `.flydocs/config.json`: tier, relay URL override.
120
+ Reads from `.flydocs/config.json`: tier, workspaceId, relay URL override.
121
121
  Reads `FLYDOCS_API_KEY` from environment or `.env` / `.env.local`.
122
122
 
123
123
  Optional: `FLYDOCS_RELAY_URL` env var or `relay.url` in config to override the base URL (e.g., for local development).
124
+
125
+ ### Header Contract
126
+
127
+ Every relay request includes:
128
+
129
+ | Header | Required | Source |
130
+ | --------------- | -------- | --------------------------------------------------- |
131
+ | `Authorization` | Yes | `Bearer fdk_...` from `FLYDOCS_API_KEY` |
132
+ | `X-Workspace` | Yes\* | `workspaceId` from `.flydocs/config.json` |
133
+ | `X-Repo` | No | Git remote slug (auto-detected, e.g., `owner/repo`) |
134
+
135
+ \*Required for all endpoints except `POST /auth/validate`.
@@ -11,6 +11,7 @@ Usage:
11
11
 
12
12
  import json
13
13
  import os
14
+ import subprocess
14
15
  import sys
15
16
  import time
16
17
  from pathlib import Path
@@ -43,6 +44,7 @@ class FlyDocsClient:
43
44
  print("Run 'flydocs setup' to configure your workspace", file=sys.stderr)
44
45
  sys.exit(1)
45
46
 
47
+ self.repo_slug = self._detect_repo_slug()
46
48
  self.base_url = self._resolve_base_url()
47
49
 
48
50
  def _load_config(self) -> dict:
@@ -74,6 +76,22 @@ class FlyDocsClient:
74
76
  return v if v else None
75
77
  return None
76
78
 
79
+ def _detect_repo_slug(self) -> Optional[str]:
80
+ """Derive owner/repo slug from git remote origin URL."""
81
+ try:
82
+ url = subprocess.check_output(
83
+ ["git", "remote", "get-url", "origin"],
84
+ stderr=subprocess.DEVNULL,
85
+ timeout=5,
86
+ ).decode().strip()
87
+ if url.endswith(".git"):
88
+ url = url[:-4]
89
+ if ":" in url and "@" in url:
90
+ return url.split(":")[-1] # SSH: git@github.com:owner/repo
91
+ return "/".join(url.split("/")[-2:]) # HTTPS
92
+ except Exception:
93
+ return None
94
+
77
95
  def _resolve_base_url(self) -> str:
78
96
  """Resolve base URL: env var > config > default."""
79
97
  env_url = os.environ.get("FLYDOCS_RELAY_URL")
@@ -103,6 +121,8 @@ class FlyDocsClient:
103
121
  "Content-Type": "application/json",
104
122
  "Accept": "application/json",
105
123
  }
124
+ if self.repo_slug:
125
+ headers["X-Repo"] = self.repo_slug
106
126
 
107
127
  data = json.dumps(body).encode("utf-8") if body else None
108
128
 
@@ -1,9 +1,13 @@
1
1
  #!/usr/bin/env python3
2
2
  """Validate workspace setup via the FlyDocs Relay API.
3
3
 
4
- Read-only validation that checks provider, team, status mapping, label config,
5
- and user identity. Writes result to .flydocs/validation-cache.json and sets
6
- setupComplete: true in config when all required checks pass.
4
+ Read-only validation that calls GET /auth/config. The relay returns:
5
+ - valid: bool (all required checks pass)
6
+ - missing: ["provider", "statusMapping", ...] (required, blocks setup)
7
+ - warnings: ["repos", ...] (optional, informational)
8
+
9
+ Writes result to .flydocs/validation-cache.json and sets
10
+ setupComplete: true in config when valid is true.
7
11
  """
8
12
 
9
13
  import json
@@ -15,71 +19,48 @@ sys.path.insert(0, str(Path(__file__).parent))
15
19
  from flydocs_api import get_client, output_json, fail
16
20
 
17
21
 
18
- # Required checks failure blocks setup completion
19
- REQUIRED_CHECKS = {
20
- "provider": {
21
- "test": lambda cfg: cfg.get("provider", {}).get("connected") is True,
22
- "message": "No provider connected — configure in FlyDocs dashboard",
23
- },
24
- "team": {
25
- "test": lambda cfg: bool(cfg.get("team", {}).get("id")),
26
- "message": "No team selected — configure in FlyDocs dashboard",
27
- },
28
- "statusMapping": {
29
- "test": lambda cfg: cfg.get("statusMapping", {}).get("configured") is True,
30
- "message": "Status mapping not configured — configure in FlyDocs dashboard",
31
- },
32
- "labelConfig": {
33
- "test": lambda cfg: cfg.get("labelConfig", {}).get("configured") is True,
34
- "message": "Label config not configured — configure in FlyDocs dashboard",
35
- },
22
+ # Human-readable messages for missing/warning items
23
+ CHECK_MESSAGES: dict[str, str] = {
24
+ "provider": "No provider connected — configure in FlyDocs dashboard",
25
+ "team": "No team selected configure in FlyDocs dashboard",
26
+ "statusMapping": "Status mapping not configured — configure in FlyDocs dashboard",
27
+ "labelConfig": "Label config not configured — configure in FlyDocs dashboard",
28
+ "userIdentity": (
29
+ "Provider identity not linked — run: "
30
+ "python3 .claude/skills/flydocs-cloud/scripts/set_identity.py <provider> <id>"
31
+ ),
32
+ "repos": "No repos linked — GitHub features won't work until you push and link a repo",
36
33
  }
37
34
 
38
- # Optional checkswarn but don't block
39
- OPTIONAL_CHECKS = {
40
- "userIdentity": {
41
- "test": lambda cfg: cfg.get("userIdentity", {}).get("linked") is True,
42
- "message": (
43
- "Provider identity not linked — run: "
44
- "python3 .claude/skills/flydocs-cloud/scripts/set_identity.py <provider> <id>"
45
- ),
46
- },
47
- "repos": {
48
- "test": lambda cfg: (cfg.get("repos", {}).get("count", 0) or 0) > 0,
49
- "message": "No repos linked — link a repo in FlyDocs dashboard settings",
50
- },
51
- }
35
+ DEFAULT_MESSAGE = "Not configured check FlyDocs dashboard"
52
36
 
53
37
 
54
38
  def main() -> None:
55
39
  client = get_client()
56
40
 
57
- # Fetch workspace config from relay
41
+ # Fetch workspace config from relay — relay does the validation
58
42
  config_response = client.get("/auth/config")
59
43
 
60
- # Run checks
44
+ # Read relay-computed validation results
45
+ is_valid = config_response.get("valid", False)
46
+ missing_keys: list[str] = config_response.get("missing", [])
47
+ warning_keys: list[str] = config_response.get("warnings", [])
48
+
49
+ # Build structured missing/warning lists with messages
50
+ missing = [
51
+ {"check": k, "action": CHECK_MESSAGES.get(k, DEFAULT_MESSAGE)}
52
+ for k in missing_keys
53
+ ]
54
+ warnings = [
55
+ {"check": k, "action": CHECK_MESSAGES.get(k, DEFAULT_MESSAGE)}
56
+ for k in warning_keys
57
+ ]
58
+
59
+ # Build checks map for cache
60
+ all_keys = set(CHECK_MESSAGES.keys())
61
61
  checks: dict[str, bool] = {}
62
- valid: list[str] = []
63
- missing: list[dict[str, str]] = []
64
- warnings: list[dict[str, str]] = []
65
-
66
- for name, check in REQUIRED_CHECKS.items():
67
- passed = check["test"](config_response)
68
- checks[name] = passed
69
- if passed:
70
- valid.append(name)
71
- else:
72
- missing.append({"check": name, "action": check["message"]})
73
-
74
- for name, check in OPTIONAL_CHECKS.items():
75
- passed = check["test"](config_response)
76
- checks[name] = passed
77
- if passed:
78
- valid.append(name)
79
- else:
80
- warnings.append({"check": name, "action": check["message"]})
81
-
82
- all_required_pass = len(missing) == 0
62
+ for k in all_keys:
63
+ checks[k] = k not in missing_keys and k not in warning_keys
83
64
 
84
65
  # Build workspace info from response
85
66
  workspace = config_response.get("workspace", {})
@@ -88,15 +69,15 @@ def main() -> None:
88
69
  # Write validation cache
89
70
  cache = {
90
71
  "timestamp": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
91
- "valid": all_required_pass,
72
+ "valid": is_valid,
92
73
  "workspace": {
93
74
  "id": workspace.get("id", ""),
94
75
  "name": workspace.get("name", ""),
95
76
  },
96
77
  "provider": provider_type,
97
78
  "checks": checks,
98
- "missing": [m["check"] for m in missing],
99
- "warnings": [w["check"] for w in warnings],
79
+ "missing": missing_keys,
80
+ "warnings": warning_keys,
100
81
  }
101
82
 
102
83
  cache_path = client.project_root / ".flydocs" / "validation-cache.json"
@@ -106,7 +87,7 @@ def main() -> None:
106
87
  f.write("\n")
107
88
 
108
89
  # If all required checks pass, set setupComplete in config
109
- if all_required_pass:
90
+ if is_valid:
110
91
  config_path = client.config_path
111
92
  if config_path.exists():
112
93
  with open(config_path, "r") as f:
@@ -121,15 +102,15 @@ def main() -> None:
121
102
 
122
103
  # Output structured report
123
104
  report: dict = {
124
- "valid": all_required_pass,
105
+ "valid": is_valid,
125
106
  "checks": checks,
126
- "passed": valid,
107
+ "passed": [k for k, v in checks.items() if v],
127
108
  }
128
109
  if missing:
129
110
  report["missing"] = missing
130
111
  if warnings:
131
112
  report["warnings"] = warnings
132
- if all_required_pass:
113
+ if is_valid:
133
114
  report["setupComplete"] = True
134
115
 
135
116
  output_json(report)
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.0-alpha.10",
2
+ "version": "0.6.0-alpha.11",
3
3
  "sourceRepo": "github.com/plastrlab/flydocs-core",
4
4
  "tier": "local",
5
5
  "setupComplete": false,
@@ -1 +1 @@
1
- 0.6.0-alpha.10
1
+ 0.6.0-alpha.11
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.0-alpha.10",
2
+ "version": "0.6.0-alpha.11",
3
3
  "description": "FlyDocs Core - Manifest of all managed files",
4
4
  "repository": "github.com/plastrlab/flydocs-core",
5
5